diff --git a/.buildkite/disabled_jest_configs.json b/.buildkite/disabled_jest_configs.json index fe51488c7066f..0d7741e60b385 100644 --- a/.buildkite/disabled_jest_configs.json +++ b/.buildkite/disabled_jest_configs.json @@ -1 +1,3 @@ -[] +[ + "x-pack/plugins/index_management/jest.config.js" +] \ No newline at end of file diff --git a/.buildkite/ftr_configs.yml b/.buildkite/ftr_configs.yml index cc67d14eefcf8..4a2f50f9e3a29 100644 --- a/.buildkite/ftr_configs.yml +++ b/.buildkite/ftr_configs.yml @@ -222,12 +222,10 @@ enabled: - x-pack/test/cases_api_integration/spaces_only/config.ts - x-pack/test/cloud_security_posture_functional/config.ts - x-pack/test/cloud_security_posture_api/config.ts + - x-pack/test/dataset_quality_api_integration/basic/config.ts - x-pack/test/detection_engine_api_integration/basic/config.ts - x-pack/test/detection_engine_api_integration/security_and_spaces/group1/config.ts - - x-pack/test/detection_engine_api_integration/security_and_spaces/group4/config.ts - - x-pack/test/detection_engine_api_integration/security_and_spaces/group5/config.ts - x-pack/test/detection_engine_api_integration/security_and_spaces/group10/config.ts - - x-pack/test/detection_engine_api_integration/security_and_spaces/rule_execution_logic/config.ts - x-pack/test/disable_ems/config.ts - x-pack/test/encrypted_saved_objects_api_integration/config.ts - x-pack/test/examples/config.ts @@ -450,10 +448,14 @@ enabled: - x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/exceptions/workflows/configs/ess.config.ts - x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/exceptions/operators_data_types/date_numeric_types/configs/serverless.config.ts - x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/exceptions/operators_data_types/date_numeric_types/configs/ess.config.ts - - x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/exceptions/operators_data_types/keyword_text_long/configs/serverless.config.ts - - x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/exceptions/operators_data_types/keyword_text_long/configs/ess.config.ts - - x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/exceptions/operators_data_types/ips_text_array/configs/serverless.config.ts - - x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/exceptions/operators_data_types/ips_text_array/configs/ess.config.ts + - x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/exceptions/operators_data_types/ips/configs/serverless.config.ts + - x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/exceptions/operators_data_types/ips/configs/ess.config.ts + - x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/exceptions/operators_data_types/keyword/configs/serverless.config.ts + - x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/exceptions/operators_data_types/keyword/configs/ess.config.ts + - x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/exceptions/operators_data_types/long/configs/serverless.config.ts + - x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/exceptions/operators_data_types/long/configs/ess.config.ts + - x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/exceptions/operators_data_types/text/configs/serverless.config.ts + - x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/exceptions/operators_data_types/text/configs/ess.config.ts - x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/rule_creation/configs/serverless.config.ts - x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/rule_creation/configs/ess.config.ts - x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/actions/configs/serverless.config.ts @@ -470,3 +472,9 @@ enabled: - x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/prebuilt_rules/large_prebuilt_rules_package/configs/ess.config.ts - x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/prebuilt_rules/update_prebuilt_rules_package/configs/serverless.config.ts - x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/prebuilt_rules/update_prebuilt_rules_package/configs/ess.config.ts + - x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/rule_execution_logic/configs/serverless.config.ts + - x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/rule_execution_logic/configs/ess.config.ts + - x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/user_roles/configs/serverless.config.ts + - x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/user_roles/configs/ess.config.ts + - x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/telemetry/configs/serverless.config.ts + - x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/telemetry/configs/ess.config.ts diff --git a/.buildkite/pipelines/quality-gates/pipeline.tests-qa.yaml b/.buildkite/pipelines/quality-gates/pipeline.tests-qa.yaml index c72d3e078c879..feac7bdb17848 100644 --- a/.buildkite/pipelines/quality-gates/pipeline.tests-qa.yaml +++ b/.buildkite/pipelines/quality-gates/pipeline.tests-qa.yaml @@ -52,7 +52,7 @@ steps: - label: ":judge::seedling: Trigger Manual Tests Phase - Observability" command: "make -C /agent trigger-manual-verification-phase" env: - NOTIFICATION_APPENDIX: " please execute your manual testing plan." + NOTIFICATION_APPENDIX: " please execute your manual testing plan." USE_GROUP_LABEL: true agents: image: "docker.elastic.co/ci-agent-images/manual-verification-agent:0.0.6" diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 97560f4dfa64e..a17c788699938 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -39,8 +39,8 @@ packages/analytics/shippers/gainsight @elastic/kibana-core packages/kbn-apm-config-loader @elastic/kibana-core @vigneshshanmugam x-pack/plugins/apm_data_access @elastic/obs-knowledge-team @elastic/obs-ux-infra_services-team x-pack/plugins/apm @elastic/obs-ux-infra_services-team -packages/kbn-apm-synthtrace @elastic/obs-ux-infra_services-team -packages/kbn-apm-synthtrace-client @elastic/obs-ux-infra_services-team +packages/kbn-apm-synthtrace @elastic/obs-ux-infra_services-team @elastic/obs-ux-logs-team +packages/kbn-apm-synthtrace-client @elastic/obs-ux-infra_services-team @elastic/obs-ux-logs-team packages/kbn-apm-utils @elastic/obs-ux-infra_services-team test/plugin_functional/plugins/app_link_test @elastic/kibana-core x-pack/test/usage_collection/plugins/application_usage_test @elastic/kibana-core @@ -419,7 +419,6 @@ x-pack/examples/gen_ai_streaming_response_example @elastic/response-ops packages/kbn-generate @elastic/kibana-operations packages/kbn-generate-console-definitions @elastic/platform-deployment-management packages/kbn-generate-csv @elastic/appex-sharedux -packages/kbn-generate-csv-types @elastic/appex-sharedux packages/kbn-get-repo-files @elastic/kibana-operations x-pack/plugins/global_search_bar @elastic/appex-sharedux x-pack/plugins/global_search @elastic/appex-sharedux @@ -592,7 +591,16 @@ packages/kbn-repo-source-classifier @elastic/kibana-operations packages/kbn-repo-source-classifier-cli @elastic/kibana-operations packages/kbn-reporting/common @elastic/appex-sharedux x-pack/examples/reporting_example @elastic/appex-sharedux +packages/kbn-reporting/export_types/csv @elastic/appex-sharedux +packages/kbn-reporting/export_types/csv_common @elastic/appex-sharedux +packages/kbn-reporting/export_types/pdf @elastic/appex-sharedux +packages/kbn-reporting/export_types/pdf_common @elastic/appex-sharedux +packages/kbn-reporting/export_types/png @elastic/appex-sharedux +packages/kbn-reporting/export_types/png_common @elastic/appex-sharedux +packages/kbn-reporting/mocks_server @elastic/appex-sharedux x-pack/plugins/reporting @elastic/appex-sharedux +packages/kbn-reporting/public @elastic/appex-sharedux +packages/kbn-reporting/server @elastic/appex-sharedux packages/kbn-resizable-layout @elastic/kibana-data-discovery examples/resizable_layout_examples @elastic/kibana-data-discovery x-pack/test/plugin_functional/plugins/resolver_test @elastic/security-solution @@ -1223,6 +1231,9 @@ x-pack/plugins/cloud_integrations/cloud_full_story/server/config.ts @elastic/kib /x-pack/test/security_solution_cypress/cypress/e2e/investigations @elastic/security-threat-hunting-investigations /x-pack/test/security_solution_cypress/cypress/e2e/sourcerer/sourcerer_timeline.cy.ts @elastic/security-threat-hunting-investigations +x-pack/test/security_solution_cypress/cypress/screens/expandable_flyout @elastic/security-threat-hunting-investigations +x-pack/test/security_solution_cypress/cypress/tasks/expandable_flyout @elastic/security-threat-hunting-investigations + /x-pack/plugins/security_solution/public/common/components/alerts_viewer @elastic/security-threat-hunting-investigations /x-pack/plugins/security_solution/public/detections/components/alerts_table/timeline_action @elastic/security-threat-hunting-investigations /x-pack/plugins/security_solution/public/common/components/event_details @elastic/security-threat-hunting-investigations @@ -1231,7 +1242,8 @@ x-pack/plugins/cloud_integrations/cloud_full_story/server/config.ts @elastic/kib /x-pack/plugins/security_solution/public/detections/components/alerts_kpis @elastic/security-threat-hunting-investigations /x-pack/plugins/security_solution/public/detections/components/alerts_table @elastic/security-threat-hunting-investigations /x-pack/plugins/security_solution/public/detections/components/alerts_info @elastic/security-threat-hunting-investigations -/x-pack/plugins/security_solution/public/flyout @elastic/security-threat-hunting-investigations +/x-pack/plugins/security_solution/public/flyout/document_details @elastic/security-threat-hunting-investigations +/x-pack/plugins/security_solution/public/flyout/shared @elastic/security-threat-hunting-investigations /x-pack/plugins/security_solution/public/resolver @elastic/security-threat-hunting-investigations /x-pack/plugins/security_solution/public/timelines @elastic/security-threat-hunting-investigations @@ -1374,6 +1386,7 @@ x-pack/test/security_solution_api_integration/test_suites/detections_response/de x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/rule_creation @elastic/security-detection-engine x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/actions @elastic/security-detection-engine x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/alerts @elastic/security-detection-engine +x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/user_roles @elastic/security-detection-engine /x-pack/plugins/security_solution/server/lib/detection_engine/scripts/roles_users @elastic/security-detection-engine ## Security Threat Intelligence - Under Security Platform @@ -1397,7 +1410,7 @@ x-pack/test/security_solution_api_integration/test_suites/detections_response/de /x-pack/plugins/security_solution/server/routes @elastic/security-detections-response @elastic/security-threat-hunting /x-pack/plugins/security_solution/server/utils @elastic/security-detections-response @elastic/security-threat-hunting x-pack/test/security_solution_api_integration/test_suites/detections_response/utils @elastic/security-detections-response - +x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/telemetry @elastic/security-detections-response ## Security Solution sub teams - security-defend-workflows /x-pack/plugins/security_solution/public/management/ @elastic/security-defend-workflows diff --git a/.github/workflows/create-deploy-tag.yml b/.github/workflows/create-deploy-tag.yml index 7ce79f2bd1c07..67fa6ca6216a3 100644 --- a/.github/workflows/create-deploy-tag.yml +++ b/.github/workflows/create-deploy-tag.yml @@ -22,7 +22,7 @@ concurrency: jobs: create-deploy-tag: # Temporary, we need a way to limit this to a GitHub team instead of specific users - if: contains('["watson","clintandrewhall","kobelb","lukeelmers","thomasneirynck","jbudz","mistic","delanni","Ikuni17","pheyos","dmlemeshko"]', github.triggering_actor) + if: contains('["watson","clintandrewhall","kobelb","lukeelmers","thomasneirynck","jbudz","mistic","delanni","Ikuni17","pheyos","dmlemeshko","mikecote"]', github.triggering_actor) runs-on: ubuntu-latest permissions: contents: write diff --git a/.i18nrc.json b/.i18nrc.json index c5f1f7053f95a..6146398873d83 100644 --- a/.i18nrc.json +++ b/.i18nrc.json @@ -90,7 +90,7 @@ "randomSampling": "x-pack/packages/kbn-random-sampling", "reactPackages": "packages/react", "textBasedEditor": "packages/kbn-text-based-editor", - "reporting": "packages/kbn-reporting/common", + "reporting": "packages/kbn-reporting", "savedObjects": "src/plugins/saved_objects", "savedObjectsFinder": "src/plugins/saved_objects_finder", "savedObjectsManagement": "src/plugins/saved_objects_management", diff --git a/api_docs/actions.mdx b/api_docs/actions.mdx index 60d85e326b22f..64143589d0167 100644 --- a/api_docs/actions.mdx +++ b/api_docs/actions.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/actions title: "actions" image: https://source.unsplash.com/400x175/?github description: API docs for the actions plugin -date: 2023-11-14 +date: 2023-11-16 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 d6cddffe50333..99efdc253e539 100644 --- a/api_docs/advanced_settings.mdx +++ b/api_docs/advanced_settings.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/advancedSettings title: "advancedSettings" image: https://source.unsplash.com/400x175/?github description: API docs for the advancedSettings plugin -date: 2023-11-14 +date: 2023-11-16 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'advancedSettings'] --- import advancedSettingsObj from './advanced_settings.devdocs.json'; diff --git a/api_docs/aiops.mdx b/api_docs/aiops.mdx index 7ecaf4eaf2137..abd069d6bcc74 100644 --- a/api_docs/aiops.mdx +++ b/api_docs/aiops.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/aiops title: "aiops" image: https://source.unsplash.com/400x175/?github description: API docs for the aiops plugin -date: 2023-11-14 +date: 2023-11-16 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'aiops'] --- import aiopsObj from './aiops.devdocs.json'; diff --git a/api_docs/alerting.devdocs.json b/api_docs/alerting.devdocs.json index e91a46ecfb7fb..9505e1de3807c 100644 --- a/api_docs/alerting.devdocs.json +++ b/api_docs/alerting.devdocs.json @@ -2728,7 +2728,7 @@ "label": "actions", "description": [], "signature": [ - "Readonly<{ frequency?: Readonly<{} & { throttle: string | null; notifyWhen: \"onActionGroupChange\" | \"onActiveAlert\" | \"onThrottleInterval\"; summary: boolean; }> | undefined; alertsFilter?: Readonly<{ query?: Readonly<{ dsl?: string | undefined; } & { kql: string; filters: Readonly<{ query?: Record | undefined; state$?: Readonly<{} & { store: string; }> | undefined; } & { meta: Record; }>[]; }> | undefined; timeframe?: Readonly<{} & { days: (2 | 7 | 6 | 5 | 4 | 3 | 1)[]; hours: Readonly<{} & { start: string; end: string; }>; timezone: string; }> | undefined; } & {}> | undefined; uuid?: string | undefined; } & { id: string; params: Record; actionTypeId: string; group: string; }>[]" + "Readonly<{ frequency?: Readonly<{} & { throttle: string | null; notifyWhen: \"onActionGroupChange\" | \"onActiveAlert\" | \"onThrottleInterval\"; summary: boolean; }> | undefined; alertsFilter?: Readonly<{ query?: Readonly<{ dsl?: string | undefined; } & { kql: string; filters: Readonly<{ query?: Record | undefined; $state?: Readonly<{} & { store: \"appState\" | \"globalState\"; }> | undefined; } & { meta: Record; }>[]; }> | undefined; timeframe?: Readonly<{} & { days: (2 | 7 | 6 | 5 | 4 | 3 | 1)[]; hours: Readonly<{} & { start: string; end: string; }>; timezone: string; }> | undefined; } & {}> | undefined; uuid?: string | undefined; useAlertDataForTemplate?: boolean | undefined; } & { id: string; params: Record; actionTypeId: string; group: string; }>[]" ], "path": "x-pack/plugins/alerting/server/application/rule/types/rule.ts", "deprecated": false, @@ -4691,11 +4691,35 @@ "signature": [ "{ getContext: () => Context; getState: () => State; getUuid: () => string; getStart: () => string | null; hasContext: () => boolean; replaceState: (state: State) => ", "Alert", - "; scheduleActions: (actionGroup: ActionGroupIds, context?: Context) => ", + "; scheduleActions: (actionGroup: ActionGroupIds, context?: Context) => ", "Alert", - "; setContext: (context: Context) => ", + "; setContext: (context: Context) => ", "Alert", - "; }" + "; }" ], "path": "x-pack/plugins/alerting/server/alert/alert.ts", "deprecated": false, @@ -8160,6 +8184,20 @@ "path": "x-pack/plugins/alerting/common/rule.ts", "deprecated": false, "trackAdoption": false + }, + { + "parentPluginId": "alerting", + "id": "def-common.RuleAction.useAlertDataForTemplate", + "type": "CompoundType", + "tags": [], + "label": "useAlertDataForTemplate", + "description": [], + "signature": [ + "boolean | undefined" + ], + "path": "x-pack/plugins/alerting/common/rule.ts", + "deprecated": false, + "trackAdoption": false } ], "initialIsOpen": false diff --git a/api_docs/alerting.mdx b/api_docs/alerting.mdx index 235b06327177f..2a7c56b3ec1e9 100644 --- a/api_docs/alerting.mdx +++ b/api_docs/alerting.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/alerting title: "alerting" image: https://source.unsplash.com/400x175/?github description: API docs for the alerting plugin -date: 2023-11-14 +date: 2023-11-16 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'alerting'] --- import alertingObj from './alerting.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/response-ops](https://github.com/orgs/elastic/teams/response-o | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 809 | 1 | 778 | 50 | +| 810 | 1 | 779 | 50 | ## Client diff --git a/api_docs/apm.devdocs.json b/api_docs/apm.devdocs.json index c35b5362dce3d..897cd39513a7b 100644 --- a/api_docs/apm.devdocs.json +++ b/api_docs/apm.devdocs.json @@ -3525,7 +3525,7 @@ "StringC", "; }>>; }>]>; }> | undefined; handler: ({}: ", "APMRouteHandlerResources", - " & { params: { path: { id: string; }; body: { label: string; url: string; } & { id?: string | undefined; filters?: { key: \"\" | \"service.name\" | \"service.environment\" | \"transaction.name\" | \"transaction.type\"; value: string; }[] | undefined; }; }; }) => Promise; } & ", + " & { params: { path: { id: string; }; body: { label: string; url: string; } & { id?: string | undefined; filters?: { key: \"\" | \"service.environment\" | \"service.name\" | \"transaction.name\" | \"transaction.type\"; value: string; }[] | undefined; }; }; }) => Promise; } & ", "APMRouteCreateOptions", "; \"POST /internal/apm/settings/custom_links\": { endpoint: \"POST /internal/apm/settings/custom_links\"; params?: ", "TypeC", @@ -3563,7 +3563,7 @@ "StringC", "; }>>; }>]>; }> | undefined; handler: ({}: ", "APMRouteHandlerResources", - " & { params: { body: { label: string; url: string; } & { id?: string | undefined; filters?: { key: \"\" | \"service.name\" | \"service.environment\" | \"transaction.name\" | \"transaction.type\"; value: string; }[] | undefined; }; }; }) => Promise; } & ", + " & { params: { body: { label: string; url: string; } & { id?: string | undefined; filters?: { key: \"\" | \"service.environment\" | \"service.name\" | \"transaction.name\" | \"transaction.type\"; value: string; }[] | undefined; }; }; }) => Promise; } & ", "APMRouteCreateOptions", "; \"GET /internal/apm/settings/custom_links\": { endpoint: \"GET /internal/apm/settings/custom_links\"; params?: ", "PartialC", diff --git a/api_docs/apm.mdx b/api_docs/apm.mdx index d9071e4fb003e..3054b4228c6b3 100644 --- a/api_docs/apm.mdx +++ b/api_docs/apm.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/apm title: "apm" image: https://source.unsplash.com/400x175/?github description: API docs for the apm plugin -date: 2023-11-14 +date: 2023-11-16 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 cc7448339efb8..1e3faec44ddb2 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: 2023-11-14 +date: 2023-11-16 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 8d2750b832890..564cc08e57cf5 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: 2023-11-14 +date: 2023-11-16 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'assetManager'] --- import assetManagerObj from './asset_manager.devdocs.json'; diff --git a/api_docs/banners.mdx b/api_docs/banners.mdx index f72615de32637..d621ec7e6c16c 100644 --- a/api_docs/banners.mdx +++ b/api_docs/banners.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/banners title: "banners" image: https://source.unsplash.com/400x175/?github description: API docs for the banners plugin -date: 2023-11-14 +date: 2023-11-16 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 229f283e48d27..c6297e0f08f47 100644 --- a/api_docs/bfetch.mdx +++ b/api_docs/bfetch.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/bfetch title: "bfetch" image: https://source.unsplash.com/400x175/?github description: API docs for the bfetch plugin -date: 2023-11-14 +date: 2023-11-16 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 d2a6857ec8bbd..14322f9c1f0ed 100644 --- a/api_docs/canvas.mdx +++ b/api_docs/canvas.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/canvas title: "canvas" image: https://source.unsplash.com/400x175/?github description: API docs for the canvas plugin -date: 2023-11-14 +date: 2023-11-16 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 4a218ad15683a..81ea481070a8d 100644 --- a/api_docs/cases.mdx +++ b/api_docs/cases.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/cases title: "cases" image: https://source.unsplash.com/400x175/?github description: API docs for the cases plugin -date: 2023-11-14 +date: 2023-11-16 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 c90a98a5b5c70..8f10078c47f8c 100644 --- a/api_docs/charts.mdx +++ b/api_docs/charts.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/charts title: "charts" image: https://source.unsplash.com/400x175/?github description: API docs for the charts plugin -date: 2023-11-14 +date: 2023-11-16 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 e055c283fca44..1deca15b7abc3 100644 --- a/api_docs/cloud.mdx +++ b/api_docs/cloud.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/cloud title: "cloud" image: https://source.unsplash.com/400x175/?github description: API docs for the cloud plugin -date: 2023-11-14 +date: 2023-11-16 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 c3830e702e027..e2da1f02675a3 100644 --- a/api_docs/cloud_data_migration.mdx +++ b/api_docs/cloud_data_migration.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/cloudDataMigration title: "cloudDataMigration" image: https://source.unsplash.com/400x175/?github description: API docs for the cloudDataMigration plugin -date: 2023-11-14 +date: 2023-11-16 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 e39eb3ad81da1..07c00eb8fa709 100644 --- a/api_docs/cloud_defend.mdx +++ b/api_docs/cloud_defend.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/cloudDefend title: "cloudDefend" image: https://source.unsplash.com/400x175/?github description: API docs for the cloudDefend plugin -date: 2023-11-14 +date: 2023-11-16 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 3c41a2ed919f4..180e2a6565f3a 100644 --- a/api_docs/cloud_experiments.mdx +++ b/api_docs/cloud_experiments.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/cloudExperiments title: "cloudExperiments" image: https://source.unsplash.com/400x175/?github description: API docs for the cloudExperiments plugin -date: 2023-11-14 +date: 2023-11-16 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 cb6f7f3319142..70873f3466d25 100644 --- a/api_docs/cloud_security_posture.mdx +++ b/api_docs/cloud_security_posture.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/cloudSecurityPosture title: "cloudSecurityPosture" image: https://source.unsplash.com/400x175/?github description: API docs for the cloudSecurityPosture plugin -date: 2023-11-14 +date: 2023-11-16 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 ce46470b6d5bb..81ea3c2c6302e 100644 --- a/api_docs/console.mdx +++ b/api_docs/console.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/console title: "console" image: https://source.unsplash.com/400x175/?github description: API docs for the console plugin -date: 2023-11-14 +date: 2023-11-16 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 2cf20bc002e98..20737866a276f 100644 --- a/api_docs/content_management.mdx +++ b/api_docs/content_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/contentManagement title: "contentManagement" image: https://source.unsplash.com/400x175/?github description: API docs for the contentManagement plugin -date: 2023-11-14 +date: 2023-11-16 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 0efff68ef0c89..ecaa1207437a9 100644 --- a/api_docs/controls.mdx +++ b/api_docs/controls.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/controls title: "controls" image: https://source.unsplash.com/400x175/?github description: API docs for the controls plugin -date: 2023-11-14 +date: 2023-11-16 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 e5be4794b1e8a..23c814c9c8c47 100644 --- a/api_docs/custom_integrations.mdx +++ b/api_docs/custom_integrations.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/customIntegrations title: "customIntegrations" image: https://source.unsplash.com/400x175/?github description: API docs for the customIntegrations plugin -date: 2023-11-14 +date: 2023-11-16 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 e9006e3f58908..bab1ba8b7e7eb 100644 --- a/api_docs/dashboard.mdx +++ b/api_docs/dashboard.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/dashboard title: "dashboard" image: https://source.unsplash.com/400x175/?github description: API docs for the dashboard plugin -date: 2023-11-14 +date: 2023-11-16 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 8e8e1b2c3babe..1388e49e66aba 100644 --- a/api_docs/dashboard_enhanced.mdx +++ b/api_docs/dashboard_enhanced.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/dashboardEnhanced title: "dashboardEnhanced" image: https://source.unsplash.com/400x175/?github description: API docs for the dashboardEnhanced plugin -date: 2023-11-14 +date: 2023-11-16 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dashboardEnhanced'] --- import dashboardEnhancedObj from './dashboard_enhanced.devdocs.json'; diff --git a/api_docs/data.devdocs.json b/api_docs/data.devdocs.json index cb6db36399917..04a304f93dd8f 100644 --- a/api_docs/data.devdocs.json +++ b/api_docs/data.devdocs.json @@ -7790,6 +7790,20 @@ "path": "src/plugins/data_views/common/types.ts", "deprecated": false, "trackAdoption": false + }, + { + "parentPluginId": "data", + "id": "def-public.GetFieldsOptions.allowHidden", + "type": "CompoundType", + "tags": [], + "label": "allowHidden", + "description": [], + "signature": [ + "boolean | undefined" + ], + "path": "src/plugins/data_views/common/types.ts", + "deprecated": false, + "trackAdoption": false } ], "initialIsOpen": false @@ -15601,7 +15615,7 @@ "signature": [ "(options: { pattern: string | string[]; metaFields?: string[] | undefined; fieldCapsOptions?: { allow_no_indices: boolean; includeUnmapped?: boolean | undefined; } | undefined; type?: string | undefined; rollupIndex?: string | undefined; indexFilter?: ", "QueryDslQueryContainer", - " | undefined; fields?: string[] | undefined; }) => Promise<{ fields: ", + " | undefined; fields?: string[] | undefined; allowHidden?: boolean | undefined; }) => Promise<{ fields: ", { "pluginId": "dataViews", "scope": "server", @@ -15724,6 +15738,20 @@ "path": "src/plugins/data_views/server/fetcher/index_patterns_fetcher.ts", "deprecated": false, "trackAdoption": false + }, + { + "parentPluginId": "data", + "id": "def-server.IndexPatternsFetcher.getFieldsForWildcard.$1.allowHidden", + "type": "CompoundType", + "tags": [], + "label": "allowHidden", + "description": [], + "signature": [ + "boolean | undefined" + ], + "path": "src/plugins/data_views/server/fetcher/index_patterns_fetcher.ts", + "deprecated": false, + "trackAdoption": false } ] } @@ -23659,6 +23687,22 @@ "path": "src/plugins/data_views/common/types.ts", "deprecated": false, "trackAdoption": false + }, + { + "parentPluginId": "data", + "id": "def-common.DataViewAttributes.allowHidden", + "type": "CompoundType", + "tags": [], + "label": "allowHidden", + "description": [ + "\nAllow hidden and system indices when loading field list" + ], + "signature": [ + "boolean | undefined" + ], + "path": "src/plugins/data_views/common/types.ts", + "deprecated": false, + "trackAdoption": false } ], "initialIsOpen": false @@ -23908,6 +23952,20 @@ "path": "src/plugins/data_views/common/types.ts", "deprecated": false, "trackAdoption": false + }, + { + "parentPluginId": "data", + "id": "def-common.GetFieldsOptions.allowHidden", + "type": "CompoundType", + "tags": [], + "label": "allowHidden", + "description": [], + "signature": [ + "boolean | undefined" + ], + "path": "src/plugins/data_views/common/types.ts", + "deprecated": false, + "trackAdoption": false } ], "initialIsOpen": false @@ -24085,7 +24143,7 @@ "section": "def-common.FieldAttrs", "text": "FieldAttrs" }, - " | undefined; allowNoIndex?: boolean | undefined; namespaces?: string[] | undefined; name?: string | undefined; }" + " | undefined; allowNoIndex?: boolean | undefined; namespaces?: string[] | undefined; name?: string | undefined; allowHidden?: boolean | undefined; }" ], "path": "src/plugins/data_views/common/expressions/load_index_pattern.ts", "deprecated": false, @@ -25212,7 +25270,7 @@ "section": "def-common.FieldAttrs", "text": "FieldAttrs" }, - " | undefined; allowNoIndex?: boolean | undefined; namespaces?: string[] | undefined; name?: string | undefined; }" + " | undefined; allowNoIndex?: boolean | undefined; namespaces?: string[] | undefined; name?: string | undefined; allowHidden?: boolean | undefined; }" ], "path": "src/plugins/data_views/common/types.ts", "deprecated": false, diff --git a/api_docs/data.mdx b/api_docs/data.mdx index dc7665b7ef1b7..1028805d3b13b 100644 --- a/api_docs/data.mdx +++ b/api_docs/data.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/data title: "data" image: https://source.unsplash.com/400x175/?github description: API docs for the data plugin -date: 2023-11-14 +date: 2023-11-16 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 | |-------------------|-----------|------------------------|-----------------| -| 3193 | 32 | 2542 | 22 | +| 3197 | 32 | 2545 | 22 | ## Client diff --git a/api_docs/data_query.mdx b/api_docs/data_query.mdx index bed7b9dd84df7..a85420c2c721d 100644 --- a/api_docs/data_query.mdx +++ b/api_docs/data_query.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/data-query title: "data.query" image: https://source.unsplash.com/400x175/?github description: API docs for the data.query plugin -date: 2023-11-14 +date: 2023-11-16 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 | |-------------------|-----------|------------------------|-----------------| -| 3193 | 32 | 2542 | 22 | +| 3197 | 32 | 2545 | 22 | ## Client diff --git a/api_docs/data_search.devdocs.json b/api_docs/data_search.devdocs.json index ba37cd5797eb7..bf6f39e5a7abc 100644 --- a/api_docs/data_search.devdocs.json +++ b/api_docs/data_search.devdocs.json @@ -19,7 +19,7 @@ "section": "def-common.ApplicationStart", "text": "ApplicationStart" }, - "; }) => { title: string; body: React.ReactNode; } | undefined" + "; }) => { title: string; body: React.ReactNode; actions?: React.ReactNode[] | undefined; } | undefined" ], "path": "src/plugins/data/public/search/search_interceptor/utils.ts", "deprecated": false, @@ -267,7 +267,7 @@ "\nCurrent session management\n{@link ISessionService}" ], "signature": [ - "{ start: () => string; readonly state$: ", + "{ start: () => string; save: () => Promise; clear: () => void; destroy: () => void; readonly state$: ", "Observable", "<", { @@ -277,7 +277,7 @@ "section": "def-public.SearchSessionState", "text": "SearchSessionState" }, - ">; save: () => Promise; clear: () => void; destroy: () => void; readonly sessionMeta$: ", + ">; readonly sessionMeta$: ", "Observable", "<", "SessionMeta", @@ -723,7 +723,7 @@ "\nCurrent session management\n{@link ISessionService}" ], "signature": [ - "{ start: () => string; readonly state$: ", + "{ start: () => string; save: () => Promise; clear: () => void; destroy: () => void; readonly state$: ", "Observable", "<", { @@ -733,7 +733,7 @@ "section": "def-public.SearchSessionState", "text": "SearchSessionState" }, - ">; save: () => Promise; clear: () => void; destroy: () => void; readonly sessionMeta$: ", + ">; readonly sessionMeta$: ", "Observable", "<", "SessionMeta", @@ -1279,7 +1279,7 @@ "label": "ISessionService", "description": [], "signature": [ - "{ start: () => string; readonly state$: ", + "{ start: () => string; save: () => Promise; clear: () => void; destroy: () => void; readonly state$: ", "Observable", "<", { @@ -1289,7 +1289,7 @@ "section": "def-public.SearchSessionState", "text": "SearchSessionState" }, - ">; save: () => Promise; clear: () => void; destroy: () => void; readonly sessionMeta$: ", + ">; readonly sessionMeta$: ", "Observable", "<", "SessionMeta", @@ -27283,8 +27283,8 @@ "pluginId": "data", "scope": "common", "docId": "kibDataSearchPluginApi", - "section": "def-common.ISearchOptions", - "text": "ISearchOptions" + "section": "def-common.SearchSourceSearchOptions", + "text": "SearchSourceSearchOptions" } ], "path": "src/plugins/data/common/search/strategies/ese_search/types.ts", diff --git a/api_docs/data_search.mdx b/api_docs/data_search.mdx index 8235b9e79b252..63aedbc218d54 100644 --- a/api_docs/data_search.mdx +++ b/api_docs/data_search.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/data-search title: "data.search" image: https://source.unsplash.com/400x175/?github description: API docs for the data.search plugin -date: 2023-11-14 +date: 2023-11-16 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 | |-------------------|-----------|------------------------|-----------------| -| 3193 | 32 | 2542 | 22 | +| 3197 | 32 | 2545 | 22 | ## Client diff --git a/api_docs/data_view_editor.mdx b/api_docs/data_view_editor.mdx index 7bff787270dca..52bcd8c7aaa6c 100644 --- a/api_docs/data_view_editor.mdx +++ b/api_docs/data_view_editor.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/dataViewEditor title: "dataViewEditor" image: https://source.unsplash.com/400x175/?github description: API docs for the dataViewEditor plugin -date: 2023-11-14 +date: 2023-11-16 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 4fe6f04345b93..02ead0b2a86ec 100644 --- a/api_docs/data_view_field_editor.mdx +++ b/api_docs/data_view_field_editor.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/dataViewFieldEditor title: "dataViewFieldEditor" image: https://source.unsplash.com/400x175/?github description: API docs for the dataViewFieldEditor plugin -date: 2023-11-14 +date: 2023-11-16 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 a26e1c2c26b99..0b12410853007 100644 --- a/api_docs/data_view_management.mdx +++ b/api_docs/data_view_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/dataViewManagement title: "dataViewManagement" image: https://source.unsplash.com/400x175/?github description: API docs for the dataViewManagement plugin -date: 2023-11-14 +date: 2023-11-16 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dataViewManagement'] --- import dataViewManagementObj from './data_view_management.devdocs.json'; diff --git a/api_docs/data_views.devdocs.json b/api_docs/data_views.devdocs.json index c4efdd100341f..96792d381cdf7 100644 --- a/api_docs/data_views.devdocs.json +++ b/api_docs/data_views.devdocs.json @@ -4488,6 +4488,22 @@ "path": "src/plugins/data_views/common/types.ts", "deprecated": false, "trackAdoption": false + }, + { + "parentPluginId": "dataViews", + "id": "def-public.DataViewAttributes.allowHidden", + "type": "CompoundType", + "tags": [], + "label": "allowHidden", + "description": [ + "\nAllow hidden and system indices when loading field list" + ], + "signature": [ + "boolean | undefined" + ], + "path": "src/plugins/data_views/common/types.ts", + "deprecated": false, + "trackAdoption": false } ], "initialIsOpen": false @@ -6164,7 +6180,7 @@ "section": "def-common.FieldAttrs", "text": "FieldAttrs" }, - " | undefined; allowNoIndex?: boolean | undefined; namespaces?: string[] | undefined; name?: string | undefined; }" + " | undefined; allowNoIndex?: boolean | undefined; namespaces?: string[] | undefined; name?: string | undefined; allowHidden?: boolean | undefined; }" ], "path": "src/plugins/data_views/common/types.ts", "deprecated": false, @@ -9221,7 +9237,7 @@ "signature": [ "(options: { pattern: string | string[]; metaFields?: string[] | undefined; fieldCapsOptions?: { allow_no_indices: boolean; includeUnmapped?: boolean | undefined; } | undefined; type?: string | undefined; rollupIndex?: string | undefined; indexFilter?: ", "QueryDslQueryContainer", - " | undefined; fields?: string[] | undefined; }) => Promise<{ fields: ", + " | undefined; fields?: string[] | undefined; allowHidden?: boolean | undefined; }) => Promise<{ fields: ", { "pluginId": "dataViews", "scope": "server", @@ -9344,6 +9360,20 @@ "path": "src/plugins/data_views/server/fetcher/index_patterns_fetcher.ts", "deprecated": false, "trackAdoption": false + }, + { + "parentPluginId": "dataViews", + "id": "def-server.IndexPatternsFetcher.getFieldsForWildcard.$1.allowHidden", + "type": "CompoundType", + "tags": [], + "label": "allowHidden", + "description": [], + "signature": [ + "boolean | undefined" + ], + "path": "src/plugins/data_views/server/fetcher/index_patterns_fetcher.ts", + "deprecated": false, + "trackAdoption": false } ] } @@ -15787,6 +15817,22 @@ "path": "src/plugins/data_views/common/types.ts", "deprecated": false, "trackAdoption": false + }, + { + "parentPluginId": "dataViews", + "id": "def-common.DataViewAttributes.allowHidden", + "type": "CompoundType", + "tags": [], + "label": "allowHidden", + "description": [ + "\nAllow hidden and system indices when loading field list" + ], + "signature": [ + "boolean | undefined" + ], + "path": "src/plugins/data_views/common/types.ts", + "deprecated": false, + "trackAdoption": false } ], "initialIsOpen": false @@ -18081,6 +18127,20 @@ "path": "src/plugins/data_views/common/types.ts", "deprecated": false, "trackAdoption": false + }, + { + "parentPluginId": "dataViews", + "id": "def-common.GetFieldsOptions.allowHidden", + "type": "CompoundType", + "tags": [], + "label": "allowHidden", + "description": [], + "signature": [ + "boolean | undefined" + ], + "path": "src/plugins/data_views/common/types.ts", + "deprecated": false, + "trackAdoption": false } ], "initialIsOpen": false @@ -18763,7 +18823,7 @@ "section": "def-common.FieldAttrs", "text": "FieldAttrs" }, - " | undefined; allowNoIndex?: boolean | undefined; namespaces?: string[] | undefined; name?: string | undefined; }" + " | undefined; allowNoIndex?: boolean | undefined; namespaces?: string[] | undefined; name?: string | undefined; allowHidden?: boolean | undefined; }" ], "path": "src/plugins/data_views/common/expressions/load_index_pattern.ts", "deprecated": false, @@ -20486,7 +20546,7 @@ "section": "def-common.FieldAttrs", "text": "FieldAttrs" }, - " | undefined; allowNoIndex?: boolean | undefined; namespaces?: string[] | undefined; name?: string | undefined; }" + " | undefined; allowNoIndex?: boolean | undefined; namespaces?: string[] | undefined; name?: string | undefined; allowHidden?: boolean | undefined; }" ], "path": "src/plugins/data_views/common/types.ts", "deprecated": false, diff --git a/api_docs/data_views.mdx b/api_docs/data_views.mdx index 445e5a85413ff..399cc8f171c19 100644 --- a/api_docs/data_views.mdx +++ b/api_docs/data_views.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/dataViews title: "dataViews" image: https://source.unsplash.com/400x175/?github description: API docs for the dataViews plugin -date: 2023-11-14 +date: 2023-11-16 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dataViews'] --- import dataViewsObj from './data_views.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 | |-------------------|-----------|------------------------|-----------------| -| 918 | 0 | 255 | 4 | +| 922 | 0 | 257 | 4 | ## Client diff --git a/api_docs/data_visualizer.mdx b/api_docs/data_visualizer.mdx index f439d2b333c28..276e39cc37316 100644 --- a/api_docs/data_visualizer.mdx +++ b/api_docs/data_visualizer.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/dataVisualizer title: "dataVisualizer" image: https://source.unsplash.com/400x175/?github description: API docs for the dataVisualizer plugin -date: 2023-11-14 +date: 2023-11-16 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 3aa45083f0771..2791eb615437a 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: 2023-11-14 +date: 2023-11-16 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 2c3708faad65d..a89f7618fd20c 100644 --- a/api_docs/deprecations_by_api.mdx +++ b/api_docs/deprecations_by_api.mdx @@ -7,7 +7,7 @@ id: kibDevDocsDeprecationsByApi slug: /kibana-dev-docs/api-meta/deprecated-api-list-by-api title: Deprecated API usage by API description: A list of deprecated APIs, which plugins are still referencing them, and when they need to be removed by. -date: 2023-11-14 +date: 2023-11-16 tags: ['contributor', 'dev', 'apidocs', 'kibana'] --- @@ -123,6 +123,8 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | canvas | - | | | spaces, savedObjectsManagement | - | | | @kbn/core, visualizations, triggersActionsUi, advancedSettings | - | +| | reporting | - | +| | @kbn/reporting-export-types-pdf, reporting | - | | | @kbn/core-elasticsearch-server-internal, @kbn/core-plugins-server-internal, observabilityOnboarding, console | - | | | @kbn/content-management-table-list-view, filesManagement | - | | | enterpriseSearch | - | @@ -192,9 +194,6 @@ Safe to remove. | | lists | | | lists | | | reporting | -| | reporting | -| | reporting | -| | reporting | | | savedObjects | | | taskManager | | | @kbn/core-saved-objects-api-browser | diff --git a/api_docs/deprecations_by_plugin.mdx b/api_docs/deprecations_by_plugin.mdx index fc044097f257e..93ec1d6ddeb59 100644 --- a/api_docs/deprecations_by_plugin.mdx +++ b/api_docs/deprecations_by_plugin.mdx @@ -7,7 +7,7 @@ id: kibDevDocsDeprecationsByPlugin slug: /kibana-dev-docs/api-meta/deprecated-api-list-by-plugin title: Deprecated API usage by plugin description: A list of deprecated APIs, which plugins are still referencing them, and when they need to be removed by. -date: 2023-11-14 +date: 2023-11-16 tags: ['contributor', 'dev', 'apidocs', 'kibana'] --- @@ -300,6 +300,14 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] +## @kbn/reporting-export-types-pdf + +| Deprecated API | Reference location(s) | Remove By | +| ---------------|-----------|-----------| +| | [printable_pdf.ts](https://github.com/elastic/kibana/tree/main/packages/kbn-reporting/export_types/pdf/printable_pdf.ts#:~:text=JobParamsPDFDeprecated), [printable_pdf.ts](https://github.com/elastic/kibana/tree/main/packages/kbn-reporting/export_types/pdf/printable_pdf.ts#:~:text=JobParamsPDFDeprecated), [printable_pdf.ts](https://github.com/elastic/kibana/tree/main/packages/kbn-reporting/export_types/pdf/printable_pdf.ts#:~:text=JobParamsPDFDeprecated) | - | + + + ## @kbn/securitysolution-data-table | Deprecated API | Reference location(s) | Remove By | @@ -521,7 +529,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | Deprecated API | Reference location(s) | Remove By | | ---------------|-----------|-----------| -| | [search_interceptor.ts](https://github.com/elastic/kibana/tree/main/src/plugins/data/public/search/search_interceptor/search_interceptor.ts#:~:text=toMountPoint), [search_interceptor.ts](https://github.com/elastic/kibana/tree/main/src/plugins/data/public/search/search_interceptor/search_interceptor.ts#:~:text=toMountPoint), [search_interceptor.ts](https://github.com/elastic/kibana/tree/main/src/plugins/data/public/search/search_interceptor/search_interceptor.ts#:~:text=toMountPoint), [search_interceptor.ts](https://github.com/elastic/kibana/tree/main/src/plugins/data/public/search/search_interceptor/search_interceptor.ts#:~:text=toMountPoint), [delete_button.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/data/public/search/session/sessions_mgmt/components/actions/delete_button.tsx#:~:text=toMountPoint), [delete_button.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/data/public/search/session/sessions_mgmt/components/actions/delete_button.tsx#:~:text=toMountPoint), [extend_button.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/data/public/search/session/sessions_mgmt/components/actions/extend_button.tsx#:~:text=toMountPoint), [extend_button.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/data/public/search/session/sessions_mgmt/components/actions/extend_button.tsx#:~:text=toMountPoint), [inspect_button.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/data/public/search/session/sessions_mgmt/components/actions/inspect_button.tsx#:~:text=toMountPoint), [inspect_button.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/data/public/search/session/sessions_mgmt/components/actions/inspect_button.tsx#:~:text=toMountPoint)+ 4 more | - | +| | [delete_button.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/data/public/search/session/sessions_mgmt/components/actions/delete_button.tsx#:~:text=toMountPoint), [delete_button.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/data/public/search/session/sessions_mgmt/components/actions/delete_button.tsx#:~:text=toMountPoint), [extend_button.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/data/public/search/session/sessions_mgmt/components/actions/extend_button.tsx#:~:text=toMountPoint), [extend_button.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/data/public/search/session/sessions_mgmt/components/actions/extend_button.tsx#:~:text=toMountPoint), [inspect_button.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/data/public/search/session/sessions_mgmt/components/actions/inspect_button.tsx#:~:text=toMountPoint), [inspect_button.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/data/public/search/session/sessions_mgmt/components/actions/inspect_button.tsx#:~:text=toMountPoint), [rename_button.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/data/public/search/session/sessions_mgmt/components/actions/rename_button.tsx#:~:text=toMountPoint), [rename_button.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/data/public/search/session/sessions_mgmt/components/actions/rename_button.tsx#:~:text=toMountPoint), [search_service.ts](https://github.com/elastic/kibana/tree/main/src/plugins/data/public/search/search_service.ts#:~:text=toMountPoint), [search_service.ts](https://github.com/elastic/kibana/tree/main/src/plugins/data/public/search/search_service.ts#:~:text=toMountPoint)+ 4 more | - | | | [session_service.ts](https://github.com/elastic/kibana/tree/main/src/plugins/data/server/search/session/session_service.ts#:~:text=authc) | - | | | [data_table.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/data/public/utils/table_inspector_view/components/data_table.tsx#:~:text=executeTriggerActions), [data_table.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/data/public/utils/table_inspector_view/components/data_table.tsx#:~:text=executeTriggerActions) | - | | | [persistable_state.ts](https://github.com/elastic/kibana/tree/main/src/plugins/data/common/query/filters/persistable_state.ts#:~:text=SavedObjectReference), [persistable_state.ts](https://github.com/elastic/kibana/tree/main/src/plugins/data/common/query/filters/persistable_state.ts#:~:text=SavedObjectReference), [persistable_state.ts](https://github.com/elastic/kibana/tree/main/src/plugins/data/common/query/filters/persistable_state.ts#:~:text=SavedObjectReference), [persistable_state.ts](https://github.com/elastic/kibana/tree/main/src/plugins/data/common/query/persistable_state.ts#:~:text=SavedObjectReference), [persistable_state.ts](https://github.com/elastic/kibana/tree/main/src/plugins/data/common/query/persistable_state.ts#:~:text=SavedObjectReference), [persistable_state.ts](https://github.com/elastic/kibana/tree/main/src/plugins/data/common/query/persistable_state.ts#:~:text=SavedObjectReference) | - | @@ -1076,8 +1084,8 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | Deprecated API | Reference location(s) | Remove By | | ---------------|-----------|-----------| -| | [index.ts](https://github.com/elastic/kibana/tree/main/src/plugins/maps_ems/server/index.ts#:~:text=license%24) | 8.8.0 | -| | [index.ts](https://github.com/elastic/kibana/tree/main/src/plugins/maps_ems/server/index.ts#:~:text=refresh) | 8.8.0 | +| | [plugin.ts](https://github.com/elastic/kibana/tree/main/src/plugins/maps_ems/server/plugin.ts#:~:text=license%24) | 8.8.0 | +| | [plugin.ts](https://github.com/elastic/kibana/tree/main/src/plugins/maps_ems/server/plugin.ts#:~:text=refresh) | 8.8.0 | @@ -1203,6 +1211,8 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | Deprecated API | Reference location(s) | Remove By | | ---------------|-----------|-----------| | | [job_failure.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/reporting/public/notifier/job_failure.tsx#:~:text=toMountPoint), [job_failure.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/reporting/public/notifier/job_failure.tsx#:~:text=toMountPoint), [job_failure.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/reporting/public/notifier/job_failure.tsx#:~:text=toMountPoint), [general_error.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/reporting/public/notifier/general_error.tsx#:~:text=toMountPoint), [general_error.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/reporting/public/notifier/general_error.tsx#:~:text=toMountPoint), [job_success.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/reporting/public/notifier/job_success.tsx#:~:text=toMountPoint), [job_success.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/reporting/public/notifier/job_success.tsx#:~:text=toMountPoint), [job_success.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/reporting/public/notifier/job_success.tsx#:~:text=toMountPoint), [job_warning_formulas.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/reporting/public/notifier/job_warning_formulas.tsx#:~:text=toMountPoint), [job_warning_formulas.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/reporting/public/notifier/job_warning_formulas.tsx#:~:text=toMountPoint)+ 9 more | - | +| | [core.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/reporting/server/core.ts#:~:text=PdfV1ExportType), [core.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/reporting/server/core.ts#:~:text=PdfV1ExportType) | - | +| | [request_handler.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/reporting/server/routes/common/generate/request_handler.test.ts#:~:text=JobParamsPDFDeprecated), [request_handler.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/reporting/server/routes/common/generate/request_handler.test.ts#:~:text=JobParamsPDFDeprecated) | - | diff --git a/api_docs/deprecations_by_team.mdx b/api_docs/deprecations_by_team.mdx index ffce665be68a0..90dde6624eb22 100644 --- a/api_docs/deprecations_by_team.mdx +++ b/api_docs/deprecations_by_team.mdx @@ -7,7 +7,7 @@ id: kibDevDocsDeprecationsDueByTeam slug: /kibana-dev-docs/api-meta/deprecations-due-by-team title: Deprecated APIs due to be removed, by team description: Lists the teams that are referencing deprecated APIs with a remove by date. -date: 2023-11-14 +date: 2023-11-16 tags: ['contributor', 'dev', 'apidocs', 'kibana'] --- @@ -52,8 +52,8 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | Plugin | Deprecated API | Reference location(s) | Remove By | | --------|-------|-----------|-----------| -| mapsEms | | [index.ts](https://github.com/elastic/kibana/tree/main/src/plugins/maps_ems/server/index.ts#:~:text=license%24) | 8.8.0 | -| mapsEms | | [index.ts](https://github.com/elastic/kibana/tree/main/src/plugins/maps_ems/server/index.ts#:~:text=refresh) | 8.8.0 | +| mapsEms | | [plugin.ts](https://github.com/elastic/kibana/tree/main/src/plugins/maps_ems/server/plugin.ts#:~:text=license%24) | 8.8.0 | +| mapsEms | | [plugin.ts](https://github.com/elastic/kibana/tree/main/src/plugins/maps_ems/server/plugin.ts#:~:text=refresh) | 8.8.0 | diff --git a/api_docs/dev_tools.mdx b/api_docs/dev_tools.mdx index b0a5d9d9908bf..6f5d7e3396c4a 100644 --- a/api_docs/dev_tools.mdx +++ b/api_docs/dev_tools.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/devTools title: "devTools" image: https://source.unsplash.com/400x175/?github description: API docs for the devTools plugin -date: 2023-11-14 +date: 2023-11-16 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 230d04788ce89..71b2e1cea2a01 100644 --- a/api_docs/discover.mdx +++ b/api_docs/discover.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/discover title: "discover" image: https://source.unsplash.com/400x175/?github description: API docs for the discover plugin -date: 2023-11-14 +date: 2023-11-16 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 0b6cd9d7b3540..9df5fae9e631f 100644 --- a/api_docs/discover_enhanced.mdx +++ b/api_docs/discover_enhanced.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/discoverEnhanced title: "discoverEnhanced" image: https://source.unsplash.com/400x175/?github description: API docs for the discoverEnhanced plugin -date: 2023-11-14 +date: 2023-11-16 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'discoverEnhanced'] --- import discoverEnhancedObj from './discover_enhanced.devdocs.json'; diff --git a/api_docs/ecs_data_quality_dashboard.mdx b/api_docs/ecs_data_quality_dashboard.mdx index 856b371d087d0..fbb6be3ad8e26 100644 --- a/api_docs/ecs_data_quality_dashboard.mdx +++ b/api_docs/ecs_data_quality_dashboard.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/ecsDataQualityDashboard title: "ecsDataQualityDashboard" image: https://source.unsplash.com/400x175/?github description: API docs for the ecsDataQualityDashboard plugin -date: 2023-11-14 +date: 2023-11-16 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 46a67d5d96cfc..dd27d3fabe5a6 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: 2023-11-14 +date: 2023-11-16 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 96d23f6f6d4d8..bfad9f63f4827 100644 --- a/api_docs/embeddable.mdx +++ b/api_docs/embeddable.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/embeddable title: "embeddable" image: https://source.unsplash.com/400x175/?github description: API docs for the embeddable plugin -date: 2023-11-14 +date: 2023-11-16 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 0ba21b09a42f7..b0a5975752c71 100644 --- a/api_docs/embeddable_enhanced.mdx +++ b/api_docs/embeddable_enhanced.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/embeddableEnhanced title: "embeddableEnhanced" image: https://source.unsplash.com/400x175/?github description: API docs for the embeddableEnhanced plugin -date: 2023-11-14 +date: 2023-11-16 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 66126c5c2c014..69551457934c1 100644 --- a/api_docs/encrypted_saved_objects.mdx +++ b/api_docs/encrypted_saved_objects.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/encryptedSavedObjects title: "encryptedSavedObjects" image: https://source.unsplash.com/400x175/?github description: API docs for the encryptedSavedObjects plugin -date: 2023-11-14 +date: 2023-11-16 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 2db33783ab3e5..d5d1d961a6c1d 100644 --- a/api_docs/enterprise_search.mdx +++ b/api_docs/enterprise_search.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/enterpriseSearch title: "enterpriseSearch" image: https://source.unsplash.com/400x175/?github description: API docs for the enterpriseSearch plugin -date: 2023-11-14 +date: 2023-11-16 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 caeb5c1b936fd..6a1598ef21c82 100644 --- a/api_docs/es_ui_shared.mdx +++ b/api_docs/es_ui_shared.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/esUiShared title: "esUiShared" image: https://source.unsplash.com/400x175/?github description: API docs for the esUiShared plugin -date: 2023-11-14 +date: 2023-11-16 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'esUiShared'] --- import esUiSharedObj from './es_ui_shared.devdocs.json'; diff --git a/api_docs/event_annotation.mdx b/api_docs/event_annotation.mdx index c394f468e6f2e..c8c74aa4937ac 100644 --- a/api_docs/event_annotation.mdx +++ b/api_docs/event_annotation.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/eventAnnotation title: "eventAnnotation" image: https://source.unsplash.com/400x175/?github description: API docs for the eventAnnotation plugin -date: 2023-11-14 +date: 2023-11-16 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 45a9544954c11..f5b2d014ce508 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: 2023-11-14 +date: 2023-11-16 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 5b5cda11c9026..4209dbd4c24be 100644 --- a/api_docs/event_log.mdx +++ b/api_docs/event_log.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/eventLog title: "eventLog" image: https://source.unsplash.com/400x175/?github description: API docs for the eventLog plugin -date: 2023-11-14 +date: 2023-11-16 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 fbfd4256d9030..8f195a5c24201 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: 2023-11-14 +date: 2023-11-16 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 41ec9183a72a3..39711a5340556 100644 --- a/api_docs/expression_error.mdx +++ b/api_docs/expression_error.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionError title: "expressionError" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionError plugin -date: 2023-11-14 +date: 2023-11-16 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionError'] --- import expressionErrorObj from './expression_error.devdocs.json'; diff --git a/api_docs/expression_gauge.devdocs.json b/api_docs/expression_gauge.devdocs.json index c09174717c09e..4ffb246b88599 100644 --- a/api_docs/expression_gauge.devdocs.json +++ b/api_docs/expression_gauge.devdocs.json @@ -913,7 +913,7 @@ }, "<", "GoalDomainRange", - ">; base?: number | undefined; actual?: number | undefined; bandFillColor?: \"ignore\" | undefined; tickValueFormatter?: \"ignore\" | undefined; labelMajor?: string | ", + ">; actual?: number | undefined; base?: number | undefined; bandFillColor?: \"ignore\" | undefined; tickValueFormatter?: \"ignore\" | undefined; labelMajor?: string | ", "GoalLabelAccessor", " | undefined; labelMinor?: string | ", "GoalLabelAccessor", @@ -1215,7 +1215,7 @@ }, "<", "GoalDomainRange", - ">; base?: number | undefined; actual?: number | undefined; bandFillColor?: \"ignore\" | undefined; tickValueFormatter?: \"ignore\" | undefined; labelMajor?: string | ", + ">; actual?: number | undefined; base?: number | undefined; bandFillColor?: \"ignore\" | undefined; tickValueFormatter?: \"ignore\" | undefined; labelMajor?: string | ", "GoalLabelAccessor", " | undefined; labelMinor?: string | ", "GoalLabelAccessor", diff --git a/api_docs/expression_gauge.mdx b/api_docs/expression_gauge.mdx index d4aae58d8e017..b4436f848d99d 100644 --- a/api_docs/expression_gauge.mdx +++ b/api_docs/expression_gauge.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionGauge title: "expressionGauge" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionGauge plugin -date: 2023-11-14 +date: 2023-11-16 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 66305178290a0..ff81db920e838 100644 --- a/api_docs/expression_heatmap.mdx +++ b/api_docs/expression_heatmap.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionHeatmap title: "expressionHeatmap" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionHeatmap plugin -date: 2023-11-14 +date: 2023-11-16 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 2b1262a528738..84b62bccb1a44 100644 --- a/api_docs/expression_image.mdx +++ b/api_docs/expression_image.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionImage title: "expressionImage" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionImage plugin -date: 2023-11-14 +date: 2023-11-16 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 ea2795773464b..490307858c686 100644 --- a/api_docs/expression_legacy_metric_vis.mdx +++ b/api_docs/expression_legacy_metric_vis.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionLegacyMetricVis title: "expressionLegacyMetricVis" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionLegacyMetricVis plugin -date: 2023-11-14 +date: 2023-11-16 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 d2ab61ade7503..03703f1840aa1 100644 --- a/api_docs/expression_metric.mdx +++ b/api_docs/expression_metric.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionMetric title: "expressionMetric" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionMetric plugin -date: 2023-11-14 +date: 2023-11-16 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 365859d62dade..05fa7dd8d18ef 100644 --- a/api_docs/expression_metric_vis.mdx +++ b/api_docs/expression_metric_vis.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionMetricVis title: "expressionMetricVis" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionMetricVis plugin -date: 2023-11-14 +date: 2023-11-16 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 baf830801c316..fc41ff6fb20d9 100644 --- a/api_docs/expression_partition_vis.mdx +++ b/api_docs/expression_partition_vis.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionPartitionVis title: "expressionPartitionVis" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionPartitionVis plugin -date: 2023-11-14 +date: 2023-11-16 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 bfac6d605de1e..b0dcd2bb7eb3a 100644 --- a/api_docs/expression_repeat_image.mdx +++ b/api_docs/expression_repeat_image.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionRepeatImage title: "expressionRepeatImage" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionRepeatImage plugin -date: 2023-11-14 +date: 2023-11-16 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 6354995af4c36..3287beca87e47 100644 --- a/api_docs/expression_reveal_image.mdx +++ b/api_docs/expression_reveal_image.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionRevealImage title: "expressionRevealImage" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionRevealImage plugin -date: 2023-11-14 +date: 2023-11-16 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 cf8e7ede1d660..46bbdf399e6c8 100644 --- a/api_docs/expression_shape.mdx +++ b/api_docs/expression_shape.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionShape title: "expressionShape" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionShape plugin -date: 2023-11-14 +date: 2023-11-16 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 4e903e895a156..5a302e8a3727a 100644 --- a/api_docs/expression_tagcloud.mdx +++ b/api_docs/expression_tagcloud.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionTagcloud title: "expressionTagcloud" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionTagcloud plugin -date: 2023-11-14 +date: 2023-11-16 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 60e6708c60fed..776e9939050e4 100644 --- a/api_docs/expression_x_y.mdx +++ b/api_docs/expression_x_y.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionXY title: "expressionXY" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionXY plugin -date: 2023-11-14 +date: 2023-11-16 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 d78dbf8fe602d..0a5f31956155a 100644 --- a/api_docs/expressions.mdx +++ b/api_docs/expressions.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressions title: "expressions" image: https://source.unsplash.com/400x175/?github description: API docs for the expressions plugin -date: 2023-11-14 +date: 2023-11-16 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 125a1054ff102..3d43ce341fbc7 100644 --- a/api_docs/features.mdx +++ b/api_docs/features.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/features title: "features" image: https://source.unsplash.com/400x175/?github description: API docs for the features plugin -date: 2023-11-14 +date: 2023-11-16 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 2a891910876bd..8d3ee144d054e 100644 --- a/api_docs/field_formats.mdx +++ b/api_docs/field_formats.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/fieldFormats title: "fieldFormats" image: https://source.unsplash.com/400x175/?github description: API docs for the fieldFormats plugin -date: 2023-11-14 +date: 2023-11-16 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'fieldFormats'] --- import fieldFormatsObj from './field_formats.devdocs.json'; diff --git a/api_docs/file_upload.mdx b/api_docs/file_upload.mdx index 962b579a00944..97d7ebfb2f5b3 100644 --- a/api_docs/file_upload.mdx +++ b/api_docs/file_upload.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/fileUpload title: "fileUpload" image: https://source.unsplash.com/400x175/?github description: API docs for the fileUpload plugin -date: 2023-11-14 +date: 2023-11-16 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 fe22a5a96a6a2..f2663b244e344 100644 --- a/api_docs/files.mdx +++ b/api_docs/files.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/files title: "files" image: https://source.unsplash.com/400x175/?github description: API docs for the files plugin -date: 2023-11-14 +date: 2023-11-16 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 7ad63d8a72487..db553dcf2263a 100644 --- a/api_docs/files_management.mdx +++ b/api_docs/files_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/filesManagement title: "filesManagement" image: https://source.unsplash.com/400x175/?github description: API docs for the filesManagement plugin -date: 2023-11-14 +date: 2023-11-16 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 70d72df7dda0d..6aedc7943b644 100644 --- a/api_docs/fleet.devdocs.json +++ b/api_docs/fleet.devdocs.json @@ -4829,7 +4829,11 @@ "\nList agents" ], "signature": [ - "(options: Readonly<{ page?: number | undefined; perPage?: number | undefined; kuery?: any; sortField?: string | undefined; sortOrder?: \"asc\" | \"desc\" | undefined; showUpgradeable?: boolean | undefined; } & {}> & { showInactive: boolean; }) => Promise<{ agents: ", + "(options: Readonly<{ page?: number | undefined; perPage?: number | undefined; kuery?: any; sortField?: string | undefined; sortOrder?: \"asc\" | \"desc\" | undefined; showUpgradeable?: boolean | undefined; } & {}> & { showInactive: boolean; aggregations?: Record | undefined; searchAfter?: ", + "SortResults", + " | undefined; pitId?: string | undefined; getStatusSummary?: boolean | undefined; }) => Promise<{ agents: ", { "pluginId": "fleet", "scope": "common", @@ -4837,7 +4841,9 @@ "section": "def-common.Agent", "text": "Agent" }, - "[]; total: number; page: number; perPage: number; }>" + "[]; total: number; page: number; perPage: number; aggregations?: Record | undefined; }>" ], "path": "x-pack/plugins/fleet/server/services/agents/agent_service.ts", "deprecated": false, @@ -4851,7 +4857,11 @@ "label": "options", "description": [], "signature": [ - "Readonly<{ page?: number | undefined; perPage?: number | undefined; kuery?: any; sortField?: string | undefined; sortOrder?: \"asc\" | \"desc\" | undefined; showUpgradeable?: boolean | undefined; } & {}> & { showInactive: boolean; }" + "Readonly<{ page?: number | undefined; perPage?: number | undefined; kuery?: any; sortField?: string | undefined; sortOrder?: \"asc\" | \"desc\" | undefined; showUpgradeable?: boolean | undefined; } & {}> & { showInactive: boolean; aggregations?: Record | undefined; searchAfter?: ", + "SortResults", + " | undefined; pitId?: string | undefined; getStatusSummary?: boolean | undefined; }" ], "path": "x-pack/plugins/fleet/server/services/agents/agent_service.ts", "deprecated": false, @@ -22479,7 +22489,7 @@ "label": "owner", "description": [], "signature": [ - "{ github: string; }" + "{ github: string; type?: \"elastic\" | \"partner\" | \"community\" | undefined; }" ], "path": "x-pack/plugins/fleet/common/types/models/package_spec.ts", "deprecated": false, diff --git a/api_docs/fleet.mdx b/api_docs/fleet.mdx index 917d21b444592..98c3b0c71954c 100644 --- a/api_docs/fleet.mdx +++ b/api_docs/fleet.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/fleet title: "fleet" image: https://source.unsplash.com/400x175/?github description: API docs for the fleet plugin -date: 2023-11-14 +date: 2023-11-16 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'fleet'] --- import fleetObj from './fleet.devdocs.json'; diff --git a/api_docs/global_search.mdx b/api_docs/global_search.mdx index 9d432df5675f5..9bbc2d194bf10 100644 --- a/api_docs/global_search.mdx +++ b/api_docs/global_search.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/globalSearch title: "globalSearch" image: https://source.unsplash.com/400x175/?github description: API docs for the globalSearch plugin -date: 2023-11-14 +date: 2023-11-16 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 0f9a8ebbd4be0..4daaac8bc9109 100644 --- a/api_docs/guided_onboarding.mdx +++ b/api_docs/guided_onboarding.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/guidedOnboarding title: "guidedOnboarding" image: https://source.unsplash.com/400x175/?github description: API docs for the guidedOnboarding plugin -date: 2023-11-14 +date: 2023-11-16 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 bf992179f1b2f..f015c61e918cf 100644 --- a/api_docs/home.mdx +++ b/api_docs/home.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/home title: "home" image: https://source.unsplash.com/400x175/?github description: API docs for the home plugin -date: 2023-11-14 +date: 2023-11-16 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 1a870394fe1f6..8b37c7c3f558a 100644 --- a/api_docs/image_embeddable.mdx +++ b/api_docs/image_embeddable.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/imageEmbeddable title: "imageEmbeddable" image: https://source.unsplash.com/400x175/?github description: API docs for the imageEmbeddable plugin -date: 2023-11-14 +date: 2023-11-16 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 104157c4de0ee..d728f1d5e1647 100644 --- a/api_docs/index_lifecycle_management.mdx +++ b/api_docs/index_lifecycle_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/indexLifecycleManagement title: "indexLifecycleManagement" image: https://source.unsplash.com/400x175/?github description: API docs for the indexLifecycleManagement plugin -date: 2023-11-14 +date: 2023-11-16 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 428b110e86ab4..d99952c4838c8 100644 --- a/api_docs/index_management.mdx +++ b/api_docs/index_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/indexManagement title: "indexManagement" image: https://source.unsplash.com/400x175/?github description: API docs for the indexManagement plugin -date: 2023-11-14 +date: 2023-11-16 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 1e064f0431c68..19401203c7f51 100644 --- a/api_docs/infra.mdx +++ b/api_docs/infra.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/infra title: "infra" image: https://source.unsplash.com/400x175/?github description: API docs for the infra plugin -date: 2023-11-14 +date: 2023-11-16 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'infra'] --- import infraObj from './infra.devdocs.json'; diff --git a/api_docs/inspector.mdx b/api_docs/inspector.mdx index 194f85838dcc2..0cc16e89bd7d4 100644 --- a/api_docs/inspector.mdx +++ b/api_docs/inspector.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/inspector title: "inspector" image: https://source.unsplash.com/400x175/?github description: API docs for the inspector plugin -date: 2023-11-14 +date: 2023-11-16 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'inspector'] --- import inspectorObj from './inspector.devdocs.json'; diff --git a/api_docs/interactive_setup.mdx b/api_docs/interactive_setup.mdx index 8a96e9b99cdb5..63d7438c8904d 100644 --- a/api_docs/interactive_setup.mdx +++ b/api_docs/interactive_setup.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/interactiveSetup title: "interactiveSetup" image: https://source.unsplash.com/400x175/?github description: API docs for the interactiveSetup plugin -date: 2023-11-14 +date: 2023-11-16 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'interactiveSetup'] --- import interactiveSetupObj from './interactive_setup.devdocs.json'; diff --git a/api_docs/kbn_ace.mdx b/api_docs/kbn_ace.mdx index 064f99c177f04..189b6610ee659 100644 --- a/api_docs/kbn_ace.mdx +++ b/api_docs/kbn_ace.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ace title: "@kbn/ace" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ace plugin -date: 2023-11-14 +date: 2023-11-16 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ace'] --- import kbnAceObj from './kbn_ace.devdocs.json'; diff --git a/api_docs/kbn_aiops_components.mdx b/api_docs/kbn_aiops_components.mdx index eb1c1b6d554a9..aabb76d630a7b 100644 --- a/api_docs/kbn_aiops_components.mdx +++ b/api_docs/kbn_aiops_components.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-aiops-components title: "@kbn/aiops-components" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/aiops-components plugin -date: 2023-11-14 +date: 2023-11-16 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/aiops-components'] --- import kbnAiopsComponentsObj from './kbn_aiops_components.devdocs.json'; diff --git a/api_docs/kbn_aiops_utils.mdx b/api_docs/kbn_aiops_utils.mdx index 56d6e0ee728d3..23e0ca70b44cf 100644 --- a/api_docs/kbn_aiops_utils.mdx +++ b/api_docs/kbn_aiops_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-aiops-utils title: "@kbn/aiops-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/aiops-utils plugin -date: 2023-11-14 +date: 2023-11-16 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/aiops-utils'] --- import kbnAiopsUtilsObj from './kbn_aiops_utils.devdocs.json'; diff --git a/api_docs/kbn_alerting_api_integration_helpers.mdx b/api_docs/kbn_alerting_api_integration_helpers.mdx index 8a89654d21ade..76f8c964865d5 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: 2023-11-14 +date: 2023-11-16 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_state_types.mdx b/api_docs/kbn_alerting_state_types.mdx index dce00b8a21878..c5357a0678468 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: 2023-11-14 +date: 2023-11-16 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/alerting-state-types'] --- import kbnAlertingStateTypesObj from './kbn_alerting_state_types.devdocs.json'; diff --git a/api_docs/kbn_alerts_as_data_utils.mdx b/api_docs/kbn_alerts_as_data_utils.mdx index 3c05cbfbf692e..14d1758ac4e23 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: 2023-11-14 +date: 2023-11-16 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 d8fa08b4b640a..fe156ca3268c5 100644 --- a/api_docs/kbn_alerts_ui_shared.mdx +++ b/api_docs/kbn_alerts_ui_shared.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-alerts-ui-shared title: "@kbn/alerts-ui-shared" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/alerts-ui-shared plugin -date: 2023-11-14 +date: 2023-11-16 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 0f7e3a93fe923..41da2e03a3d14 100644 --- a/api_docs/kbn_analytics.mdx +++ b/api_docs/kbn_analytics.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-analytics title: "@kbn/analytics" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/analytics plugin -date: 2023-11-14 +date: 2023-11-16 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 26c16146589e4..05b22ea25bd41 100644 --- a/api_docs/kbn_analytics_client.mdx +++ b/api_docs/kbn_analytics_client.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-analytics-client title: "@kbn/analytics-client" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/analytics-client plugin -date: 2023-11-14 +date: 2023-11-16 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.devdocs.json b/api_docs/kbn_analytics_collection_utils.devdocs.json new file mode 100644 index 0000000000000..3a3a34e764e58 --- /dev/null +++ b/api_docs/kbn_analytics_collection_utils.devdocs.json @@ -0,0 +1,47 @@ +{ + "id": "@kbn/analytics-collection-utils", + "client": { + "classes": [], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] + }, + "server": { + "classes": [], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] + }, + "common": { + "classes": [], + "functions": [ + { + "parentPluginId": "@kbn/analytics-collection-utils", + "id": "def-common.isSyntheticsMonitor", + "type": "Function", + "tags": [], + "label": "isSyntheticsMonitor", + "description": [ + "\nReturns whether the current navigation is performed by a Synthetics monitor\n(and hence, telemetry should not be collected)." + ], + "signature": [ + "() => boolean" + ], + "path": "packages/analytics/utils/analytics_collection_utils/src/is_synthetics_monitor.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [], + "initialIsOpen": false + } + ], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] + } +} \ No newline at end of file diff --git a/api_docs/kbn_analytics_collection_utils.mdx b/api_docs/kbn_analytics_collection_utils.mdx new file mode 100644 index 0000000000000..f1cf88e92bbaa --- /dev/null +++ b/api_docs/kbn_analytics_collection_utils.mdx @@ -0,0 +1,30 @@ +--- +#### +#### 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: kibKbnAnalyticsCollectionUtilsPluginApi +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: 2023-11-16 +tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/analytics-collection-utils'] +--- +import kbnAnalyticsCollectionUtilsObj from './kbn_analytics_collection_utils.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 | +|-------------------|-----------|------------------------|-----------------| +| 1 | 0 | 0 | 0 | + +## Common + +### Functions + + diff --git a/api_docs/kbn_analytics_shippers_elastic_v3_browser.mdx b/api_docs/kbn_analytics_shippers_elastic_v3_browser.mdx index 9e5d32bbce526..409d8363c8987 100644 --- a/api_docs/kbn_analytics_shippers_elastic_v3_browser.mdx +++ b/api_docs/kbn_analytics_shippers_elastic_v3_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-analytics-shippers-elastic-v3-browser title: "@kbn/analytics-shippers-elastic-v3-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/analytics-shippers-elastic-v3-browser plugin -date: 2023-11-14 +date: 2023-11-16 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 a9d55c8b263c3..92ee042360f6f 100644 --- a/api_docs/kbn_analytics_shippers_elastic_v3_common.mdx +++ b/api_docs/kbn_analytics_shippers_elastic_v3_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-analytics-shippers-elastic-v3-common title: "@kbn/analytics-shippers-elastic-v3-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/analytics-shippers-elastic-v3-common plugin -date: 2023-11-14 +date: 2023-11-16 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 3781d6ccfc8ab..609bfbb645caf 100644 --- a/api_docs/kbn_analytics_shippers_elastic_v3_server.mdx +++ b/api_docs/kbn_analytics_shippers_elastic_v3_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-analytics-shippers-elastic-v3-server title: "@kbn/analytics-shippers-elastic-v3-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/analytics-shippers-elastic-v3-server plugin -date: 2023-11-14 +date: 2023-11-16 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 9899ca45221e6..c0222701054b5 100644 --- a/api_docs/kbn_analytics_shippers_fullstory.mdx +++ b/api_docs/kbn_analytics_shippers_fullstory.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-analytics-shippers-fullstory title: "@kbn/analytics-shippers-fullstory" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/analytics-shippers-fullstory plugin -date: 2023-11-14 +date: 2023-11-16 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/analytics-shippers-fullstory'] --- import kbnAnalyticsShippersFullstoryObj from './kbn_analytics_shippers_fullstory.devdocs.json'; diff --git a/api_docs/kbn_analytics_shippers_gainsight.mdx b/api_docs/kbn_analytics_shippers_gainsight.mdx index 9d508bdf04630..73674f838d059 100644 --- a/api_docs/kbn_analytics_shippers_gainsight.mdx +++ b/api_docs/kbn_analytics_shippers_gainsight.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-analytics-shippers-gainsight title: "@kbn/analytics-shippers-gainsight" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/analytics-shippers-gainsight plugin -date: 2023-11-14 +date: 2023-11-16 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/analytics-shippers-gainsight'] --- import kbnAnalyticsShippersGainsightObj from './kbn_analytics_shippers_gainsight.devdocs.json'; diff --git a/api_docs/kbn_apm_config_loader.mdx b/api_docs/kbn_apm_config_loader.mdx index 76ea0e0712cd2..d6f27633bf48b 100644 --- a/api_docs/kbn_apm_config_loader.mdx +++ b/api_docs/kbn_apm_config_loader.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-apm-config-loader title: "@kbn/apm-config-loader" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/apm-config-loader plugin -date: 2023-11-14 +date: 2023-11-16 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/apm-config-loader'] --- import kbnApmConfigLoaderObj from './kbn_apm_config_loader.devdocs.json'; diff --git a/api_docs/kbn_apm_synthtrace.mdx b/api_docs/kbn_apm_synthtrace.mdx index 62e71a21a17b8..8a707c835f0f0 100644 --- a/api_docs/kbn_apm_synthtrace.mdx +++ b/api_docs/kbn_apm_synthtrace.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-apm-synthtrace title: "@kbn/apm-synthtrace" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/apm-synthtrace plugin -date: 2023-11-14 +date: 2023-11-16 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.devdocs.json b/api_docs/kbn_apm_synthtrace_client.devdocs.json index 2bd574701728d..fed87d8205926 100644 --- a/api_docs/kbn_apm_synthtrace_client.devdocs.json +++ b/api_docs/kbn_apm_synthtrace_client.devdocs.json @@ -2437,7 +2437,7 @@ "section": "def-common.ApmFields", "text": "ApmFields" }, - ", \"@timestamp\" | \"ecs.version\" | \"observer.version_major\" | \"processor.event\" | \"event.ingested\" | \"observer.type\" | \"observer.version\" | \"metricset.name\" | \"processor.name\"> & Partial<{ 'labels.etag': string; agent_config_applied: number; 'event.agent_id_status': string; }>" + ", \"@timestamp\" | \"processor.event\" | \"ecs.version\" | \"event.ingested\" | \"observer.type\" | \"observer.version\" | \"observer.version_major\" | \"metricset.name\" | \"processor.name\"> & Partial<{ 'labels.etag': string; agent_config_applied: number; 'event.agent_id_status': string; }>" ], "path": "packages/kbn-apm-synthtrace-client/src/lib/agent_config/agent_config_fields.ts", "deprecated": false, diff --git a/api_docs/kbn_apm_synthtrace_client.mdx b/api_docs/kbn_apm_synthtrace_client.mdx index ad226a42732d1..312a88198bc42 100644 --- a/api_docs/kbn_apm_synthtrace_client.mdx +++ b/api_docs/kbn_apm_synthtrace_client.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-apm-synthtrace-client title: "@kbn/apm-synthtrace-client" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/apm-synthtrace-client plugin -date: 2023-11-14 +date: 2023-11-16 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 55543edc5b3de..7af7f1cef044f 100644 --- a/api_docs/kbn_apm_utils.mdx +++ b/api_docs/kbn_apm_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-apm-utils title: "@kbn/apm-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/apm-utils plugin -date: 2023-11-14 +date: 2023-11-16 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 76bcfb7888c10..e89aa154d812f 100644 --- a/api_docs/kbn_axe_config.mdx +++ b/api_docs/kbn_axe_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-axe-config title: "@kbn/axe-config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/axe-config plugin -date: 2023-11-14 +date: 2023-11-16 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/axe-config'] --- import kbnAxeConfigObj from './kbn_axe_config.devdocs.json'; diff --git a/api_docs/kbn_cases_components.mdx b/api_docs/kbn_cases_components.mdx index 3d8ac75b0a667..5f522e29787b4 100644 --- a/api_docs/kbn_cases_components.mdx +++ b/api_docs/kbn_cases_components.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-cases-components title: "@kbn/cases-components" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/cases-components plugin -date: 2023-11-14 +date: 2023-11-16 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 dcbed958dc1b1..3fa31abc0ff29 100644 --- a/api_docs/kbn_cell_actions.mdx +++ b/api_docs/kbn_cell_actions.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-cell-actions title: "@kbn/cell-actions" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/cell-actions plugin -date: 2023-11-14 +date: 2023-11-16 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 62a30938068f7..2af9ff7332b85 100644 --- a/api_docs/kbn_chart_expressions_common.mdx +++ b/api_docs/kbn_chart_expressions_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-chart-expressions-common title: "@kbn/chart-expressions-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/chart-expressions-common plugin -date: 2023-11-14 +date: 2023-11-16 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 d6306e31b0b27..3eeaf3cd311cb 100644 --- a/api_docs/kbn_chart_icons.mdx +++ b/api_docs/kbn_chart_icons.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-chart-icons title: "@kbn/chart-icons" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/chart-icons plugin -date: 2023-11-14 +date: 2023-11-16 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 4632895e454ca..7462733fc884f 100644 --- a/api_docs/kbn_ci_stats_core.mdx +++ b/api_docs/kbn_ci_stats_core.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ci-stats-core title: "@kbn/ci-stats-core" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ci-stats-core plugin -date: 2023-11-14 +date: 2023-11-16 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 11d527796c875..3de480ed21955 100644 --- a/api_docs/kbn_ci_stats_performance_metrics.mdx +++ b/api_docs/kbn_ci_stats_performance_metrics.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ci-stats-performance-metrics title: "@kbn/ci-stats-performance-metrics" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ci-stats-performance-metrics plugin -date: 2023-11-14 +date: 2023-11-16 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 100e0a93cc8ae..04e7240b39f84 100644 --- a/api_docs/kbn_ci_stats_reporter.mdx +++ b/api_docs/kbn_ci_stats_reporter.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ci-stats-reporter title: "@kbn/ci-stats-reporter" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ci-stats-reporter plugin -date: 2023-11-14 +date: 2023-11-16 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 13cd5694a153f..106c7c3e03f4c 100644 --- a/api_docs/kbn_cli_dev_mode.mdx +++ b/api_docs/kbn_cli_dev_mode.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-cli-dev-mode title: "@kbn/cli-dev-mode" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/cli-dev-mode plugin -date: 2023-11-14 +date: 2023-11-16 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 04ac564bd32e0..4acc329f7b742 100644 --- a/api_docs/kbn_code_editor.mdx +++ b/api_docs/kbn_code_editor.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-code-editor title: "@kbn/code-editor" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/code-editor plugin -date: 2023-11-14 +date: 2023-11-16 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/code-editor'] --- import kbnCodeEditorObj from './kbn_code_editor.devdocs.json'; diff --git a/api_docs/kbn_coloring.mdx b/api_docs/kbn_coloring.mdx index 84031ce239a4e..b278289fb313a 100644 --- a/api_docs/kbn_coloring.mdx +++ b/api_docs/kbn_coloring.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-coloring title: "@kbn/coloring" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/coloring plugin -date: 2023-11-14 +date: 2023-11-16 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 45a54c46fe8f5..8a9bde089c70e 100644 --- a/api_docs/kbn_config.mdx +++ b/api_docs/kbn_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-config title: "@kbn/config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/config plugin -date: 2023-11-14 +date: 2023-11-16 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 67ce45b7f8df5..e192ffcfa0ad1 100644 --- a/api_docs/kbn_config_mocks.mdx +++ b/api_docs/kbn_config_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-config-mocks title: "@kbn/config-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/config-mocks plugin -date: 2023-11-14 +date: 2023-11-16 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 021b44c7a6ff0..54faa957e183a 100644 --- a/api_docs/kbn_config_schema.mdx +++ b/api_docs/kbn_config_schema.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-config-schema title: "@kbn/config-schema" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/config-schema plugin -date: 2023-11-14 +date: 2023-11-16 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 cc09784f0dc3d..e0502e8116459 100644 --- a/api_docs/kbn_content_management_content_editor.mdx +++ b/api_docs/kbn_content_management_content_editor.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-content-management-content-editor title: "@kbn/content-management-content-editor" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/content-management-content-editor plugin -date: 2023-11-14 +date: 2023-11-16 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 10874e550daa2..e2d7cf44bf718 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: 2023-11-14 +date: 2023-11-16 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 fd914ddd18bc8..ad5d44921985b 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: 2023-11-14 +date: 2023-11-16 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_table.mdx b/api_docs/kbn_content_management_table_list_view_table.mdx index fedd98cd66e46..8702d5fdb32c5 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: 2023-11-14 +date: 2023-11-16 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 dc93b744a7ab6..7e84e380d6e1c 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: 2023-11-14 +date: 2023-11-16 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 a3109846ba360..fda7f80ae2ea2 100644 --- a/api_docs/kbn_core_analytics_browser.mdx +++ b/api_docs/kbn_core_analytics_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-analytics-browser title: "@kbn/core-analytics-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-analytics-browser plugin -date: 2023-11-14 +date: 2023-11-16 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 02c2ad54a81fd..96fc078ccc245 100644 --- a/api_docs/kbn_core_analytics_browser_internal.mdx +++ b/api_docs/kbn_core_analytics_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-analytics-browser-internal title: "@kbn/core-analytics-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-analytics-browser-internal plugin -date: 2023-11-14 +date: 2023-11-16 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 526bb20e23514..39b7d6ab11ef8 100644 --- a/api_docs/kbn_core_analytics_browser_mocks.mdx +++ b/api_docs/kbn_core_analytics_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-analytics-browser-mocks title: "@kbn/core-analytics-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-analytics-browser-mocks plugin -date: 2023-11-14 +date: 2023-11-16 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 4a09e2f4e1542..b71dcc4c4afd6 100644 --- a/api_docs/kbn_core_analytics_server.mdx +++ b/api_docs/kbn_core_analytics_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-analytics-server title: "@kbn/core-analytics-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-analytics-server plugin -date: 2023-11-14 +date: 2023-11-16 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 8bc5f2ab125ac..f3658c59f301d 100644 --- a/api_docs/kbn_core_analytics_server_internal.mdx +++ b/api_docs/kbn_core_analytics_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-analytics-server-internal title: "@kbn/core-analytics-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-analytics-server-internal plugin -date: 2023-11-14 +date: 2023-11-16 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 f03033a25621a..1ff31f38bea3f 100644 --- a/api_docs/kbn_core_analytics_server_mocks.mdx +++ b/api_docs/kbn_core_analytics_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-analytics-server-mocks title: "@kbn/core-analytics-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-analytics-server-mocks plugin -date: 2023-11-14 +date: 2023-11-16 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 8fab7372bda73..ffdcb671242e9 100644 --- a/api_docs/kbn_core_application_browser.mdx +++ b/api_docs/kbn_core_application_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-application-browser title: "@kbn/core-application-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-application-browser plugin -date: 2023-11-14 +date: 2023-11-16 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 9e1d1136c8777..b81dc0db543ff 100644 --- a/api_docs/kbn_core_application_browser_internal.mdx +++ b/api_docs/kbn_core_application_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-application-browser-internal title: "@kbn/core-application-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-application-browser-internal plugin -date: 2023-11-14 +date: 2023-11-16 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 2ec54d95e10ae..728714013ec78 100644 --- a/api_docs/kbn_core_application_browser_mocks.mdx +++ b/api_docs/kbn_core_application_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-application-browser-mocks title: "@kbn/core-application-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-application-browser-mocks plugin -date: 2023-11-14 +date: 2023-11-16 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 65001f8d5766f..5807d0ccae700 100644 --- a/api_docs/kbn_core_application_common.mdx +++ b/api_docs/kbn_core_application_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-application-common title: "@kbn/core-application-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-application-common plugin -date: 2023-11-14 +date: 2023-11-16 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 ef63e1aecb763..dc71b26849f48 100644 --- a/api_docs/kbn_core_apps_browser_internal.mdx +++ b/api_docs/kbn_core_apps_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-apps-browser-internal title: "@kbn/core-apps-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-apps-browser-internal plugin -date: 2023-11-14 +date: 2023-11-16 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 62559532eaf30..0ee803e0744ea 100644 --- a/api_docs/kbn_core_apps_browser_mocks.mdx +++ b/api_docs/kbn_core_apps_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-apps-browser-mocks title: "@kbn/core-apps-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-apps-browser-mocks plugin -date: 2023-11-14 +date: 2023-11-16 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 2a4dba7e0390a..eaabeb2aba8e4 100644 --- a/api_docs/kbn_core_apps_server_internal.mdx +++ b/api_docs/kbn_core_apps_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-apps-server-internal title: "@kbn/core-apps-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-apps-server-internal plugin -date: 2023-11-14 +date: 2023-11-16 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 3345b88c81d19..c3cf9ff8c65f7 100644 --- a/api_docs/kbn_core_base_browser_mocks.mdx +++ b/api_docs/kbn_core_base_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-base-browser-mocks title: "@kbn/core-base-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-base-browser-mocks plugin -date: 2023-11-14 +date: 2023-11-16 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 d25609a188af3..2025c1859d305 100644 --- a/api_docs/kbn_core_base_common.mdx +++ b/api_docs/kbn_core_base_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-base-common title: "@kbn/core-base-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-base-common plugin -date: 2023-11-14 +date: 2023-11-16 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 c24313559302b..46b5ea9148310 100644 --- a/api_docs/kbn_core_base_server_internal.mdx +++ b/api_docs/kbn_core_base_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-base-server-internal title: "@kbn/core-base-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-base-server-internal plugin -date: 2023-11-14 +date: 2023-11-16 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 b2c5c930df758..c2956651186b5 100644 --- a/api_docs/kbn_core_base_server_mocks.mdx +++ b/api_docs/kbn_core_base_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-base-server-mocks title: "@kbn/core-base-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-base-server-mocks plugin -date: 2023-11-14 +date: 2023-11-16 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 ae7640109ec09..00dafd0d77c00 100644 --- a/api_docs/kbn_core_capabilities_browser_mocks.mdx +++ b/api_docs/kbn_core_capabilities_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-capabilities-browser-mocks title: "@kbn/core-capabilities-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-capabilities-browser-mocks plugin -date: 2023-11-14 +date: 2023-11-16 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 708b8faa55d5b..5d371de09c55e 100644 --- a/api_docs/kbn_core_capabilities_common.mdx +++ b/api_docs/kbn_core_capabilities_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-capabilities-common title: "@kbn/core-capabilities-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-capabilities-common plugin -date: 2023-11-14 +date: 2023-11-16 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 550c4b5a1656d..f1378e9adc70c 100644 --- a/api_docs/kbn_core_capabilities_server.mdx +++ b/api_docs/kbn_core_capabilities_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-capabilities-server title: "@kbn/core-capabilities-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-capabilities-server plugin -date: 2023-11-14 +date: 2023-11-16 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 68255dfa4c1cc..42b48847c1dc7 100644 --- a/api_docs/kbn_core_capabilities_server_mocks.mdx +++ b/api_docs/kbn_core_capabilities_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-capabilities-server-mocks title: "@kbn/core-capabilities-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-capabilities-server-mocks plugin -date: 2023-11-14 +date: 2023-11-16 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 110332f69ba44..8db90e89076f4 100644 --- a/api_docs/kbn_core_chrome_browser.mdx +++ b/api_docs/kbn_core_chrome_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-chrome-browser title: "@kbn/core-chrome-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-chrome-browser plugin -date: 2023-11-14 +date: 2023-11-16 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 0dfcd4f519756..8218a43de3ef6 100644 --- a/api_docs/kbn_core_chrome_browser_mocks.mdx +++ b/api_docs/kbn_core_chrome_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-chrome-browser-mocks title: "@kbn/core-chrome-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-chrome-browser-mocks plugin -date: 2023-11-14 +date: 2023-11-16 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 f21f06afe4297..9ee0774c8ef8d 100644 --- a/api_docs/kbn_core_config_server_internal.mdx +++ b/api_docs/kbn_core_config_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-config-server-internal title: "@kbn/core-config-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-config-server-internal plugin -date: 2023-11-14 +date: 2023-11-16 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 8a0830cd060d1..5f619525c811b 100644 --- a/api_docs/kbn_core_custom_branding_browser.mdx +++ b/api_docs/kbn_core_custom_branding_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-custom-branding-browser title: "@kbn/core-custom-branding-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-custom-branding-browser plugin -date: 2023-11-14 +date: 2023-11-16 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 ed32d89905241..8e2b103fd6d0d 100644 --- a/api_docs/kbn_core_custom_branding_browser_internal.mdx +++ b/api_docs/kbn_core_custom_branding_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-custom-branding-browser-internal title: "@kbn/core-custom-branding-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-custom-branding-browser-internal plugin -date: 2023-11-14 +date: 2023-11-16 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 1d0af77e8b44c..92a3b393312a1 100644 --- a/api_docs/kbn_core_custom_branding_browser_mocks.mdx +++ b/api_docs/kbn_core_custom_branding_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-custom-branding-browser-mocks title: "@kbn/core-custom-branding-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-custom-branding-browser-mocks plugin -date: 2023-11-14 +date: 2023-11-16 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 3bcf1fc00e518..98d7ccc849ffe 100644 --- a/api_docs/kbn_core_custom_branding_common.mdx +++ b/api_docs/kbn_core_custom_branding_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-custom-branding-common title: "@kbn/core-custom-branding-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-custom-branding-common plugin -date: 2023-11-14 +date: 2023-11-16 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 4655731b8d1ef..6d596de7ccd1b 100644 --- a/api_docs/kbn_core_custom_branding_server.mdx +++ b/api_docs/kbn_core_custom_branding_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-custom-branding-server title: "@kbn/core-custom-branding-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-custom-branding-server plugin -date: 2023-11-14 +date: 2023-11-16 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 1794f470411b2..cd145170012d7 100644 --- a/api_docs/kbn_core_custom_branding_server_internal.mdx +++ b/api_docs/kbn_core_custom_branding_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-custom-branding-server-internal title: "@kbn/core-custom-branding-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-custom-branding-server-internal plugin -date: 2023-11-14 +date: 2023-11-16 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 b418c95ac275a..b3c56d63cce16 100644 --- a/api_docs/kbn_core_custom_branding_server_mocks.mdx +++ b/api_docs/kbn_core_custom_branding_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-custom-branding-server-mocks title: "@kbn/core-custom-branding-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-custom-branding-server-mocks plugin -date: 2023-11-14 +date: 2023-11-16 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 1945714ec421c..1c85a8bf3ba70 100644 --- a/api_docs/kbn_core_deprecations_browser.mdx +++ b/api_docs/kbn_core_deprecations_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-deprecations-browser title: "@kbn/core-deprecations-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-deprecations-browser plugin -date: 2023-11-14 +date: 2023-11-16 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 8e9c710845778..bb1e47e819956 100644 --- a/api_docs/kbn_core_deprecations_browser_internal.mdx +++ b/api_docs/kbn_core_deprecations_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-deprecations-browser-internal title: "@kbn/core-deprecations-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-deprecations-browser-internal plugin -date: 2023-11-14 +date: 2023-11-16 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 d0ad4b2f7fe24..5b7ed830d6a54 100644 --- a/api_docs/kbn_core_deprecations_browser_mocks.mdx +++ b/api_docs/kbn_core_deprecations_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-deprecations-browser-mocks title: "@kbn/core-deprecations-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-deprecations-browser-mocks plugin -date: 2023-11-14 +date: 2023-11-16 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 5d86fcd925d60..1516f640f69d7 100644 --- a/api_docs/kbn_core_deprecations_common.mdx +++ b/api_docs/kbn_core_deprecations_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-deprecations-common title: "@kbn/core-deprecations-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-deprecations-common plugin -date: 2023-11-14 +date: 2023-11-16 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 5de8e487fb87f..939aa1d4781ef 100644 --- a/api_docs/kbn_core_deprecations_server.mdx +++ b/api_docs/kbn_core_deprecations_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-deprecations-server title: "@kbn/core-deprecations-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-deprecations-server plugin -date: 2023-11-14 +date: 2023-11-16 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 8f7bc29ebf46d..b8ec0277deff1 100644 --- a/api_docs/kbn_core_deprecations_server_internal.mdx +++ b/api_docs/kbn_core_deprecations_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-deprecations-server-internal title: "@kbn/core-deprecations-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-deprecations-server-internal plugin -date: 2023-11-14 +date: 2023-11-16 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 0edb8eeccf299..0d897a649adc0 100644 --- a/api_docs/kbn_core_deprecations_server_mocks.mdx +++ b/api_docs/kbn_core_deprecations_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-deprecations-server-mocks title: "@kbn/core-deprecations-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-deprecations-server-mocks plugin -date: 2023-11-14 +date: 2023-11-16 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 7d2f9fe452152..bdaaf1d44fccb 100644 --- a/api_docs/kbn_core_doc_links_browser.mdx +++ b/api_docs/kbn_core_doc_links_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-doc-links-browser title: "@kbn/core-doc-links-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-doc-links-browser plugin -date: 2023-11-14 +date: 2023-11-16 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 97b75f91797c7..cdd5e7c326e8a 100644 --- a/api_docs/kbn_core_doc_links_browser_mocks.mdx +++ b/api_docs/kbn_core_doc_links_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-doc-links-browser-mocks title: "@kbn/core-doc-links-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-doc-links-browser-mocks plugin -date: 2023-11-14 +date: 2023-11-16 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 eae124612fe3e..a2fb261fc8f01 100644 --- a/api_docs/kbn_core_doc_links_server.mdx +++ b/api_docs/kbn_core_doc_links_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-doc-links-server title: "@kbn/core-doc-links-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-doc-links-server plugin -date: 2023-11-14 +date: 2023-11-16 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 24fcc817342fa..729b38e60a5c3 100644 --- a/api_docs/kbn_core_doc_links_server_mocks.mdx +++ b/api_docs/kbn_core_doc_links_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-doc-links-server-mocks title: "@kbn/core-doc-links-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-doc-links-server-mocks plugin -date: 2023-11-14 +date: 2023-11-16 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 17d7f1da59dd4..ad7f55b1e5bfd 100644 --- a/api_docs/kbn_core_elasticsearch_client_server_internal.mdx +++ b/api_docs/kbn_core_elasticsearch_client_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-elasticsearch-client-server-internal title: "@kbn/core-elasticsearch-client-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-elasticsearch-client-server-internal plugin -date: 2023-11-14 +date: 2023-11-16 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 1130ec94a10e9..14c49dcb61f0d 100644 --- a/api_docs/kbn_core_elasticsearch_client_server_mocks.mdx +++ b/api_docs/kbn_core_elasticsearch_client_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-elasticsearch-client-server-mocks title: "@kbn/core-elasticsearch-client-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-elasticsearch-client-server-mocks plugin -date: 2023-11-14 +date: 2023-11-16 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.devdocs.json b/api_docs/kbn_core_elasticsearch_server.devdocs.json index b926e48892b73..5b1adab029495 100644 --- a/api_docs/kbn_core_elasticsearch_server.devdocs.json +++ b/api_docs/kbn_core_elasticsearch_server.devdocs.json @@ -1032,7 +1032,7 @@ "Headers used for authentication against Elasticsearch" ], "signature": [ - "{ date?: string | string[] | undefined; warning?: string | string[] | undefined; range?: string | string[] | undefined; from?: string | string[] | undefined; etag?: string | string[] | undefined; accept?: string | string[] | undefined; \"accept-language\"?: string | string[] | undefined; \"accept-patch\"?: string | string[] | undefined; \"accept-ranges\"?: string | string[] | undefined; \"access-control-allow-credentials\"?: string | string[] | undefined; \"access-control-allow-headers\"?: string | string[] | undefined; \"access-control-allow-methods\"?: string | string[] | undefined; \"access-control-allow-origin\"?: string | string[] | undefined; \"access-control-expose-headers\"?: string | string[] | undefined; \"access-control-max-age\"?: string | string[] | undefined; \"access-control-request-headers\"?: string | string[] | undefined; \"access-control-request-method\"?: string | string[] | undefined; age?: string | string[] | undefined; allow?: string | string[] | undefined; \"alt-svc\"?: string | string[] | undefined; authorization?: string | string[] | undefined; \"cache-control\"?: string | string[] | undefined; connection?: string | string[] | undefined; \"content-disposition\"?: string | string[] | undefined; \"content-encoding\"?: string | string[] | undefined; \"content-language\"?: string | string[] | undefined; \"content-length\"?: string | string[] | undefined; \"content-location\"?: string | string[] | undefined; \"content-range\"?: string | string[] | undefined; \"content-type\"?: string | string[] | undefined; cookie?: string | string[] | undefined; expect?: string | string[] | undefined; expires?: string | string[] | undefined; forwarded?: string | string[] | undefined; host?: string | string[] | undefined; \"if-match\"?: string | string[] | undefined; \"if-modified-since\"?: string | string[] | undefined; \"if-none-match\"?: string | string[] | undefined; \"if-unmodified-since\"?: string | string[] | undefined; \"last-modified\"?: string | string[] | undefined; location?: string | string[] | undefined; origin?: string | string[] | undefined; pragma?: string | string[] | undefined; \"proxy-authenticate\"?: string | string[] | undefined; \"proxy-authorization\"?: string | string[] | undefined; \"public-key-pins\"?: string | string[] | undefined; referer?: string | string[] | undefined; \"retry-after\"?: string | string[] | undefined; \"sec-websocket-accept\"?: string | string[] | undefined; \"sec-websocket-extensions\"?: string | string[] | undefined; \"sec-websocket-key\"?: string | string[] | undefined; \"sec-websocket-protocol\"?: string | string[] | undefined; \"sec-websocket-version\"?: string | string[] | undefined; \"set-cookie\"?: string | string[] | undefined; \"strict-transport-security\"?: string | string[] | undefined; tk?: string | string[] | undefined; trailer?: string | string[] | undefined; \"transfer-encoding\"?: string | string[] | undefined; upgrade?: string | string[] | undefined; \"user-agent\"?: string | string[] | undefined; vary?: string | string[] | undefined; via?: string | string[] | undefined; \"www-authenticate\"?: string | string[] | undefined; } & { [header: string]: string | string[] | undefined; }" + "{ date?: string | string[] | undefined; warning?: string | string[] | undefined; location?: string | string[] | undefined; range?: string | string[] | undefined; from?: string | string[] | undefined; etag?: string | string[] | undefined; accept?: string | string[] | undefined; \"accept-language\"?: string | string[] | undefined; \"accept-patch\"?: string | string[] | undefined; \"accept-ranges\"?: string | string[] | undefined; \"access-control-allow-credentials\"?: string | string[] | undefined; \"access-control-allow-headers\"?: string | string[] | undefined; \"access-control-allow-methods\"?: string | string[] | undefined; \"access-control-allow-origin\"?: string | string[] | undefined; \"access-control-expose-headers\"?: string | string[] | undefined; \"access-control-max-age\"?: string | string[] | undefined; \"access-control-request-headers\"?: string | string[] | undefined; \"access-control-request-method\"?: string | string[] | undefined; age?: string | string[] | undefined; allow?: string | string[] | undefined; \"alt-svc\"?: string | string[] | undefined; authorization?: string | string[] | undefined; \"cache-control\"?: string | string[] | undefined; connection?: string | string[] | undefined; \"content-disposition\"?: string | string[] | undefined; \"content-encoding\"?: string | string[] | undefined; \"content-language\"?: string | string[] | undefined; \"content-length\"?: string | string[] | undefined; \"content-location\"?: string | string[] | undefined; \"content-range\"?: string | string[] | undefined; \"content-type\"?: string | string[] | undefined; cookie?: string | string[] | undefined; expect?: string | string[] | undefined; expires?: string | string[] | undefined; forwarded?: string | string[] | undefined; host?: string | string[] | undefined; \"if-match\"?: string | string[] | undefined; \"if-modified-since\"?: string | string[] | undefined; \"if-none-match\"?: string | string[] | undefined; \"if-unmodified-since\"?: string | string[] | undefined; \"last-modified\"?: string | string[] | undefined; origin?: string | string[] | undefined; pragma?: string | string[] | undefined; \"proxy-authenticate\"?: string | string[] | undefined; \"proxy-authorization\"?: string | string[] | undefined; \"public-key-pins\"?: string | string[] | undefined; referer?: string | string[] | undefined; \"retry-after\"?: string | string[] | undefined; \"sec-websocket-accept\"?: string | string[] | undefined; \"sec-websocket-extensions\"?: string | string[] | undefined; \"sec-websocket-key\"?: string | string[] | undefined; \"sec-websocket-protocol\"?: string | string[] | undefined; \"sec-websocket-version\"?: string | string[] | undefined; \"set-cookie\"?: string | string[] | undefined; \"strict-transport-security\"?: string | string[] | undefined; tk?: string | string[] | undefined; trailer?: string | string[] | undefined; \"transfer-encoding\"?: string | string[] | undefined; upgrade?: string | string[] | undefined; \"user-agent\"?: string | string[] | undefined; vary?: string | string[] | undefined; via?: string | string[] | undefined; \"www-authenticate\"?: string | string[] | undefined; } & { [header: string]: string | string[] | undefined; }" ], "path": "packages/core/elasticsearch/core-elasticsearch-server/src/client/scopeable_request.ts", "deprecated": false, diff --git a/api_docs/kbn_core_elasticsearch_server.mdx b/api_docs/kbn_core_elasticsearch_server.mdx index 5a73356d390eb..7ba8917104613 100644 --- a/api_docs/kbn_core_elasticsearch_server.mdx +++ b/api_docs/kbn_core_elasticsearch_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-elasticsearch-server title: "@kbn/core-elasticsearch-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-elasticsearch-server plugin -date: 2023-11-14 +date: 2023-11-16 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.devdocs.json b/api_docs/kbn_core_elasticsearch_server_internal.devdocs.json index ddc738b65660a..82ccce9ed5415 100644 --- a/api_docs/kbn_core_elasticsearch_server_internal.devdocs.json +++ b/api_docs/kbn_core_elasticsearch_server_internal.devdocs.json @@ -1567,6 +1567,9 @@ "tags": [], "label": "cluster_build_flavor", "description": [], + "signature": [ + "string | undefined" + ], "path": "packages/core/elasticsearch/core-elasticsearch-server-internal/src/get_cluster_info.ts", "deprecated": false, "trackAdoption": false diff --git a/api_docs/kbn_core_elasticsearch_server_internal.mdx b/api_docs/kbn_core_elasticsearch_server_internal.mdx index e1e1721787740..cb8834354b9e6 100644 --- a/api_docs/kbn_core_elasticsearch_server_internal.mdx +++ b/api_docs/kbn_core_elasticsearch_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-elasticsearch-server-internal title: "@kbn/core-elasticsearch-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-elasticsearch-server-internal plugin -date: 2023-11-14 +date: 2023-11-16 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 6749cca50844b..8e11f3f668e01 100644 --- a/api_docs/kbn_core_elasticsearch_server_mocks.mdx +++ b/api_docs/kbn_core_elasticsearch_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-elasticsearch-server-mocks title: "@kbn/core-elasticsearch-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-elasticsearch-server-mocks plugin -date: 2023-11-14 +date: 2023-11-16 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 1d9bf0989e52e..fd28961e92c33 100644 --- a/api_docs/kbn_core_environment_server_internal.mdx +++ b/api_docs/kbn_core_environment_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-environment-server-internal title: "@kbn/core-environment-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-environment-server-internal plugin -date: 2023-11-14 +date: 2023-11-16 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 8cf72ba3c2186..53dbc7f736451 100644 --- a/api_docs/kbn_core_environment_server_mocks.mdx +++ b/api_docs/kbn_core_environment_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-environment-server-mocks title: "@kbn/core-environment-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-environment-server-mocks plugin -date: 2023-11-14 +date: 2023-11-16 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 e69c61e737c49..0f90f7b33c80b 100644 --- a/api_docs/kbn_core_execution_context_browser.mdx +++ b/api_docs/kbn_core_execution_context_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-execution-context-browser title: "@kbn/core-execution-context-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-execution-context-browser plugin -date: 2023-11-14 +date: 2023-11-16 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 ddb9858141446..7b896d7816398 100644 --- a/api_docs/kbn_core_execution_context_browser_internal.mdx +++ b/api_docs/kbn_core_execution_context_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-execution-context-browser-internal title: "@kbn/core-execution-context-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-execution-context-browser-internal plugin -date: 2023-11-14 +date: 2023-11-16 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 e4b8b765d6bac..825f0f87bd7eb 100644 --- a/api_docs/kbn_core_execution_context_browser_mocks.mdx +++ b/api_docs/kbn_core_execution_context_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-execution-context-browser-mocks title: "@kbn/core-execution-context-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-execution-context-browser-mocks plugin -date: 2023-11-14 +date: 2023-11-16 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 afa99fe92f85c..6e813d506614d 100644 --- a/api_docs/kbn_core_execution_context_common.mdx +++ b/api_docs/kbn_core_execution_context_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-execution-context-common title: "@kbn/core-execution-context-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-execution-context-common plugin -date: 2023-11-14 +date: 2023-11-16 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 172163e36a273..4645c255a61ed 100644 --- a/api_docs/kbn_core_execution_context_server.mdx +++ b/api_docs/kbn_core_execution_context_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-execution-context-server title: "@kbn/core-execution-context-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-execution-context-server plugin -date: 2023-11-14 +date: 2023-11-16 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 4c7019c1a5fad..8d717516e1ee8 100644 --- a/api_docs/kbn_core_execution_context_server_internal.mdx +++ b/api_docs/kbn_core_execution_context_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-execution-context-server-internal title: "@kbn/core-execution-context-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-execution-context-server-internal plugin -date: 2023-11-14 +date: 2023-11-16 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 03ffc9c8ddc76..4cc7ac4de5ed0 100644 --- a/api_docs/kbn_core_execution_context_server_mocks.mdx +++ b/api_docs/kbn_core_execution_context_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-execution-context-server-mocks title: "@kbn/core-execution-context-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-execution-context-server-mocks plugin -date: 2023-11-14 +date: 2023-11-16 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 2133a9e6f53d4..2b7657a91f4b1 100644 --- a/api_docs/kbn_core_fatal_errors_browser.mdx +++ b/api_docs/kbn_core_fatal_errors_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-fatal-errors-browser title: "@kbn/core-fatal-errors-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-fatal-errors-browser plugin -date: 2023-11-14 +date: 2023-11-16 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 02d884b531024..03cd6e56b12a8 100644 --- a/api_docs/kbn_core_fatal_errors_browser_mocks.mdx +++ b/api_docs/kbn_core_fatal_errors_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-fatal-errors-browser-mocks title: "@kbn/core-fatal-errors-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-fatal-errors-browser-mocks plugin -date: 2023-11-14 +date: 2023-11-16 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 fb1b3f67541fe..c6a24b6621717 100644 --- a/api_docs/kbn_core_http_browser.mdx +++ b/api_docs/kbn_core_http_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-browser title: "@kbn/core-http-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-browser plugin -date: 2023-11-14 +date: 2023-11-16 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 e2eca21efd91b..09c5e377e2b70 100644 --- a/api_docs/kbn_core_http_browser_internal.mdx +++ b/api_docs/kbn_core_http_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-browser-internal title: "@kbn/core-http-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-browser-internal plugin -date: 2023-11-14 +date: 2023-11-16 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 5d312eb606912..96a2ad090c401 100644 --- a/api_docs/kbn_core_http_browser_mocks.mdx +++ b/api_docs/kbn_core_http_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-browser-mocks title: "@kbn/core-http-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-browser-mocks plugin -date: 2023-11-14 +date: 2023-11-16 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 90c53e27789ce..8d8a41aa64a53 100644 --- a/api_docs/kbn_core_http_common.mdx +++ b/api_docs/kbn_core_http_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-common title: "@kbn/core-http-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-common plugin -date: 2023-11-14 +date: 2023-11-16 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 c3aaed2302120..c35ce23823fec 100644 --- a/api_docs/kbn_core_http_context_server_mocks.mdx +++ b/api_docs/kbn_core_http_context_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-context-server-mocks title: "@kbn/core-http-context-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-context-server-mocks plugin -date: 2023-11-14 +date: 2023-11-16 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 8b697dfd51e25..4e8df44698906 100644 --- a/api_docs/kbn_core_http_request_handler_context_server.mdx +++ b/api_docs/kbn_core_http_request_handler_context_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-request-handler-context-server title: "@kbn/core-http-request-handler-context-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-request-handler-context-server plugin -date: 2023-11-14 +date: 2023-11-16 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 49dbedb385821..d47c318a07078 100644 --- a/api_docs/kbn_core_http_resources_server.mdx +++ b/api_docs/kbn_core_http_resources_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-resources-server title: "@kbn/core-http-resources-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-resources-server plugin -date: 2023-11-14 +date: 2023-11-16 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 abf398d4e10f1..6ab812b7ed9ab 100644 --- a/api_docs/kbn_core_http_resources_server_internal.mdx +++ b/api_docs/kbn_core_http_resources_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-resources-server-internal title: "@kbn/core-http-resources-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-resources-server-internal plugin -date: 2023-11-14 +date: 2023-11-16 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 0f98745318f2d..2d55704c31c03 100644 --- a/api_docs/kbn_core_http_resources_server_mocks.mdx +++ b/api_docs/kbn_core_http_resources_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-resources-server-mocks title: "@kbn/core-http-resources-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-resources-server-mocks plugin -date: 2023-11-14 +date: 2023-11-16 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 eec36e9f31096..d5848e3bb43bd 100644 --- a/api_docs/kbn_core_http_router_server_internal.mdx +++ b/api_docs/kbn_core_http_router_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-router-server-internal title: "@kbn/core-http-router-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-router-server-internal plugin -date: 2023-11-14 +date: 2023-11-16 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 3ed46fb480d8f..49d307af713ed 100644 --- a/api_docs/kbn_core_http_router_server_mocks.mdx +++ b/api_docs/kbn_core_http_router_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-router-server-mocks title: "@kbn/core-http-router-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-router-server-mocks plugin -date: 2023-11-14 +date: 2023-11-16 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 7798bb1d4ebed..de83f68911548 100644 --- a/api_docs/kbn_core_http_server.devdocs.json +++ b/api_docs/kbn_core_http_server.devdocs.json @@ -748,7 +748,7 @@ "The headers associated with the request." ], "signature": [ - "{ date?: string | string[] | undefined; warning?: string | string[] | undefined; range?: string | string[] | undefined; from?: string | string[] | undefined; etag?: string | string[] | undefined; accept?: string | string[] | undefined; \"accept-language\"?: string | string[] | undefined; \"accept-patch\"?: string | string[] | undefined; \"accept-ranges\"?: string | string[] | undefined; \"access-control-allow-credentials\"?: string | string[] | undefined; \"access-control-allow-headers\"?: string | string[] | undefined; \"access-control-allow-methods\"?: string | string[] | undefined; \"access-control-allow-origin\"?: string | string[] | undefined; \"access-control-expose-headers\"?: string | string[] | undefined; \"access-control-max-age\"?: string | string[] | undefined; \"access-control-request-headers\"?: string | string[] | undefined; \"access-control-request-method\"?: string | string[] | undefined; age?: string | string[] | undefined; allow?: string | string[] | undefined; \"alt-svc\"?: string | string[] | undefined; authorization?: string | string[] | undefined; \"cache-control\"?: string | string[] | undefined; connection?: string | string[] | undefined; \"content-disposition\"?: string | string[] | undefined; \"content-encoding\"?: string | string[] | undefined; \"content-language\"?: string | string[] | undefined; \"content-length\"?: string | string[] | undefined; \"content-location\"?: string | string[] | undefined; \"content-range\"?: string | string[] | undefined; \"content-type\"?: string | string[] | undefined; cookie?: string | string[] | undefined; expect?: string | string[] | undefined; expires?: string | string[] | undefined; forwarded?: string | string[] | undefined; host?: string | string[] | undefined; \"if-match\"?: string | string[] | undefined; \"if-modified-since\"?: string | string[] | undefined; \"if-none-match\"?: string | string[] | undefined; \"if-unmodified-since\"?: string | string[] | undefined; \"last-modified\"?: string | string[] | undefined; location?: string | string[] | undefined; origin?: string | string[] | undefined; pragma?: string | string[] | undefined; \"proxy-authenticate\"?: string | string[] | undefined; \"proxy-authorization\"?: string | string[] | undefined; \"public-key-pins\"?: string | string[] | undefined; referer?: string | string[] | undefined; \"retry-after\"?: string | string[] | undefined; \"sec-websocket-accept\"?: string | string[] | undefined; \"sec-websocket-extensions\"?: string | string[] | undefined; \"sec-websocket-key\"?: string | string[] | undefined; \"sec-websocket-protocol\"?: string | string[] | undefined; \"sec-websocket-version\"?: string | string[] | undefined; \"set-cookie\"?: string | string[] | undefined; \"strict-transport-security\"?: string | string[] | undefined; tk?: string | string[] | undefined; trailer?: string | string[] | undefined; \"transfer-encoding\"?: string | string[] | undefined; upgrade?: string | string[] | undefined; \"user-agent\"?: string | string[] | undefined; vary?: string | string[] | undefined; via?: string | string[] | undefined; \"www-authenticate\"?: string | string[] | undefined; } & { [header: string]: string | string[] | undefined; }" + "{ date?: string | string[] | undefined; warning?: string | string[] | undefined; location?: string | string[] | undefined; range?: string | string[] | undefined; from?: string | string[] | undefined; etag?: string | string[] | undefined; accept?: string | string[] | undefined; \"accept-language\"?: string | string[] | undefined; \"accept-patch\"?: string | string[] | undefined; \"accept-ranges\"?: string | string[] | undefined; \"access-control-allow-credentials\"?: string | string[] | undefined; \"access-control-allow-headers\"?: string | string[] | undefined; \"access-control-allow-methods\"?: string | string[] | undefined; \"access-control-allow-origin\"?: string | string[] | undefined; \"access-control-expose-headers\"?: string | string[] | undefined; \"access-control-max-age\"?: string | string[] | undefined; \"access-control-request-headers\"?: string | string[] | undefined; \"access-control-request-method\"?: string | string[] | undefined; age?: string | string[] | undefined; allow?: string | string[] | undefined; \"alt-svc\"?: string | string[] | undefined; authorization?: string | string[] | undefined; \"cache-control\"?: string | string[] | undefined; connection?: string | string[] | undefined; \"content-disposition\"?: string | string[] | undefined; \"content-encoding\"?: string | string[] | undefined; \"content-language\"?: string | string[] | undefined; \"content-length\"?: string | string[] | undefined; \"content-location\"?: string | string[] | undefined; \"content-range\"?: string | string[] | undefined; \"content-type\"?: string | string[] | undefined; cookie?: string | string[] | undefined; expect?: string | string[] | undefined; expires?: string | string[] | undefined; forwarded?: string | string[] | undefined; host?: string | string[] | undefined; \"if-match\"?: string | string[] | undefined; \"if-modified-since\"?: string | string[] | undefined; \"if-none-match\"?: string | string[] | undefined; \"if-unmodified-since\"?: string | string[] | undefined; \"last-modified\"?: string | string[] | undefined; origin?: string | string[] | undefined; pragma?: string | string[] | undefined; \"proxy-authenticate\"?: string | string[] | undefined; \"proxy-authorization\"?: string | string[] | undefined; \"public-key-pins\"?: string | string[] | undefined; referer?: string | string[] | undefined; \"retry-after\"?: string | string[] | undefined; \"sec-websocket-accept\"?: string | string[] | undefined; \"sec-websocket-extensions\"?: string | string[] | undefined; \"sec-websocket-key\"?: string | string[] | undefined; \"sec-websocket-protocol\"?: string | string[] | undefined; \"sec-websocket-version\"?: string | string[] | undefined; \"set-cookie\"?: string | string[] | undefined; \"strict-transport-security\"?: string | string[] | undefined; tk?: string | string[] | undefined; trailer?: string | string[] | undefined; \"transfer-encoding\"?: string | string[] | undefined; upgrade?: string | string[] | undefined; \"user-agent\"?: string | string[] | undefined; vary?: string | string[] | undefined; via?: string | string[] | undefined; \"www-authenticate\"?: string | string[] | undefined; } & { [header: string]: string | string[] | undefined; }" ], "path": "packages/core/http/core-http-server/src/router/raw_request.ts", "deprecated": false, @@ -10214,7 +10214,7 @@ "\nReadonly copy of incoming request headers." ], "signature": [ - "{ date?: string | string[] | undefined; warning?: string | string[] | undefined; range?: string | string[] | undefined; from?: string | string[] | undefined; etag?: string | string[] | undefined; accept?: string | string[] | undefined; \"accept-language\"?: string | string[] | undefined; \"accept-patch\"?: string | string[] | undefined; \"accept-ranges\"?: string | string[] | undefined; \"access-control-allow-credentials\"?: string | string[] | undefined; \"access-control-allow-headers\"?: string | string[] | undefined; \"access-control-allow-methods\"?: string | string[] | undefined; \"access-control-allow-origin\"?: string | string[] | undefined; \"access-control-expose-headers\"?: string | string[] | undefined; \"access-control-max-age\"?: string | string[] | undefined; \"access-control-request-headers\"?: string | string[] | undefined; \"access-control-request-method\"?: string | string[] | undefined; age?: string | string[] | undefined; allow?: string | string[] | undefined; \"alt-svc\"?: string | string[] | undefined; authorization?: string | string[] | undefined; \"cache-control\"?: string | string[] | undefined; connection?: string | string[] | undefined; \"content-disposition\"?: string | string[] | undefined; \"content-encoding\"?: string | string[] | undefined; \"content-language\"?: string | string[] | undefined; \"content-length\"?: string | string[] | undefined; \"content-location\"?: string | string[] | undefined; \"content-range\"?: string | string[] | undefined; \"content-type\"?: string | string[] | undefined; cookie?: string | string[] | undefined; expect?: string | string[] | undefined; expires?: string | string[] | undefined; forwarded?: string | string[] | undefined; host?: string | string[] | undefined; \"if-match\"?: string | string[] | undefined; \"if-modified-since\"?: string | string[] | undefined; \"if-none-match\"?: string | string[] | undefined; \"if-unmodified-since\"?: string | string[] | undefined; \"last-modified\"?: string | string[] | undefined; location?: string | string[] | undefined; origin?: string | string[] | undefined; pragma?: string | string[] | undefined; \"proxy-authenticate\"?: string | string[] | undefined; \"proxy-authorization\"?: string | string[] | undefined; \"public-key-pins\"?: string | string[] | undefined; referer?: string | string[] | undefined; \"retry-after\"?: string | string[] | undefined; \"sec-websocket-accept\"?: string | string[] | undefined; \"sec-websocket-extensions\"?: string | string[] | undefined; \"sec-websocket-key\"?: string | string[] | undefined; \"sec-websocket-protocol\"?: string | string[] | undefined; \"sec-websocket-version\"?: string | string[] | undefined; \"set-cookie\"?: string | string[] | undefined; \"strict-transport-security\"?: string | string[] | undefined; tk?: string | string[] | undefined; trailer?: string | string[] | undefined; \"transfer-encoding\"?: string | string[] | undefined; upgrade?: string | string[] | undefined; \"user-agent\"?: string | string[] | undefined; vary?: string | string[] | undefined; via?: string | string[] | undefined; \"www-authenticate\"?: string | string[] | undefined; } & { [header: string]: string | string[] | undefined; }" + "{ date?: string | string[] | undefined; warning?: string | string[] | undefined; location?: string | string[] | undefined; range?: string | string[] | undefined; from?: string | string[] | undefined; etag?: string | string[] | undefined; accept?: string | string[] | undefined; \"accept-language\"?: string | string[] | undefined; \"accept-patch\"?: string | string[] | undefined; \"accept-ranges\"?: string | string[] | undefined; \"access-control-allow-credentials\"?: string | string[] | undefined; \"access-control-allow-headers\"?: string | string[] | undefined; \"access-control-allow-methods\"?: string | string[] | undefined; \"access-control-allow-origin\"?: string | string[] | undefined; \"access-control-expose-headers\"?: string | string[] | undefined; \"access-control-max-age\"?: string | string[] | undefined; \"access-control-request-headers\"?: string | string[] | undefined; \"access-control-request-method\"?: string | string[] | undefined; age?: string | string[] | undefined; allow?: string | string[] | undefined; \"alt-svc\"?: string | string[] | undefined; authorization?: string | string[] | undefined; \"cache-control\"?: string | string[] | undefined; connection?: string | string[] | undefined; \"content-disposition\"?: string | string[] | undefined; \"content-encoding\"?: string | string[] | undefined; \"content-language\"?: string | string[] | undefined; \"content-length\"?: string | string[] | undefined; \"content-location\"?: string | string[] | undefined; \"content-range\"?: string | string[] | undefined; \"content-type\"?: string | string[] | undefined; cookie?: string | string[] | undefined; expect?: string | string[] | undefined; expires?: string | string[] | undefined; forwarded?: string | string[] | undefined; host?: string | string[] | undefined; \"if-match\"?: string | string[] | undefined; \"if-modified-since\"?: string | string[] | undefined; \"if-none-match\"?: string | string[] | undefined; \"if-unmodified-since\"?: string | string[] | undefined; \"last-modified\"?: string | string[] | undefined; origin?: string | string[] | undefined; pragma?: string | string[] | undefined; \"proxy-authenticate\"?: string | string[] | undefined; \"proxy-authorization\"?: string | string[] | undefined; \"public-key-pins\"?: string | string[] | undefined; referer?: string | string[] | undefined; \"retry-after\"?: string | string[] | undefined; \"sec-websocket-accept\"?: string | string[] | undefined; \"sec-websocket-extensions\"?: string | string[] | undefined; \"sec-websocket-key\"?: string | string[] | undefined; \"sec-websocket-protocol\"?: string | string[] | undefined; \"sec-websocket-version\"?: string | string[] | undefined; \"set-cookie\"?: string | string[] | undefined; \"strict-transport-security\"?: string | string[] | undefined; tk?: string | string[] | undefined; trailer?: string | string[] | undefined; \"transfer-encoding\"?: string | string[] | undefined; upgrade?: string | string[] | undefined; \"user-agent\"?: string | string[] | undefined; vary?: string | string[] | undefined; via?: string | string[] | undefined; \"www-authenticate\"?: string | string[] | undefined; } & { [header: string]: string | string[] | undefined; }" ], "path": "packages/core/http/core-http-server/src/router/request.ts", "deprecated": false, @@ -13183,6 +13183,10 @@ "plugin": "ml", "path": "x-pack/plugins/ml/server/routes/management.ts" }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/services/security/fleet_router.ts" + }, { "plugin": "telemetry", "path": "src/plugins/telemetry/server/routes/telemetry_config.ts" @@ -13195,10 +13199,6 @@ "plugin": "telemetry", "path": "src/plugins/telemetry/server/routes/telemetry_last_reported.ts" }, - { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/services/security/fleet_router.ts" - }, { "plugin": "metricsDataAccess", "path": "x-pack/plugins/metrics_data_access/server/lib/adapters/framework/kibana_framework_adapter.ts" @@ -13918,6 +13918,10 @@ "plugin": "ml", "path": "x-pack/plugins/ml/server/routes/anomaly_detectors.ts" }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/services/security/fleet_router.ts" + }, { "plugin": "telemetry", "path": "src/plugins/telemetry/server/routes/telemetry_user_has_seen_notice.ts" @@ -13926,10 +13930,6 @@ "plugin": "telemetry", "path": "src/plugins/telemetry/server/routes/telemetry_last_reported.ts" }, - { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/services/security/fleet_router.ts" - }, { "plugin": "metricsDataAccess", "path": "x-pack/plugins/metrics_data_access/server/lib/adapters/framework/kibana_framework_adapter.ts" @@ -14513,6 +14513,10 @@ "plugin": "ml", "path": "x-pack/plugins/ml/server/routes/alerting.ts" }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/services/security/fleet_router.ts" + }, { "plugin": "telemetry", "path": "src/plugins/telemetry/server/routes/telemetry_opt_in_stats.ts" @@ -14525,10 +14529,6 @@ "plugin": "telemetry", "path": "src/plugins/telemetry/server/routes/telemetry_usage_stats.ts" }, - { - "plugin": "fleet", - "path": "x-pack/plugins/fleet/server/services/security/fleet_router.ts" - }, { "plugin": "metricsDataAccess", "path": "x-pack/plugins/metrics_data_access/server/lib/adapters/framework/kibana_framework_adapter.ts" @@ -15942,7 +15942,7 @@ "\nHttp request headers to read." ], "signature": [ - "{ date?: string | string[] | undefined; warning?: string | string[] | undefined; range?: string | string[] | undefined; from?: string | string[] | undefined; etag?: string | string[] | undefined; accept?: string | string[] | undefined; \"accept-language\"?: string | string[] | undefined; \"accept-patch\"?: string | string[] | undefined; \"accept-ranges\"?: string | string[] | undefined; \"access-control-allow-credentials\"?: string | string[] | undefined; \"access-control-allow-headers\"?: string | string[] | undefined; \"access-control-allow-methods\"?: string | string[] | undefined; \"access-control-allow-origin\"?: string | string[] | undefined; \"access-control-expose-headers\"?: string | string[] | undefined; \"access-control-max-age\"?: string | string[] | undefined; \"access-control-request-headers\"?: string | string[] | undefined; \"access-control-request-method\"?: string | string[] | undefined; age?: string | string[] | undefined; allow?: string | string[] | undefined; \"alt-svc\"?: string | string[] | undefined; authorization?: string | string[] | undefined; \"cache-control\"?: string | string[] | undefined; connection?: string | string[] | undefined; \"content-disposition\"?: string | string[] | undefined; \"content-encoding\"?: string | string[] | undefined; \"content-language\"?: string | string[] | undefined; \"content-length\"?: string | string[] | undefined; \"content-location\"?: string | string[] | undefined; \"content-range\"?: string | string[] | undefined; \"content-type\"?: string | string[] | undefined; cookie?: string | string[] | undefined; expect?: string | string[] | undefined; expires?: string | string[] | undefined; forwarded?: string | string[] | undefined; host?: string | string[] | undefined; \"if-match\"?: string | string[] | undefined; \"if-modified-since\"?: string | string[] | undefined; \"if-none-match\"?: string | string[] | undefined; \"if-unmodified-since\"?: string | string[] | undefined; \"last-modified\"?: string | string[] | undefined; location?: string | string[] | undefined; origin?: string | string[] | undefined; pragma?: string | string[] | undefined; \"proxy-authenticate\"?: string | string[] | undefined; \"proxy-authorization\"?: string | string[] | undefined; \"public-key-pins\"?: string | string[] | undefined; referer?: string | string[] | undefined; \"retry-after\"?: string | string[] | undefined; \"sec-websocket-accept\"?: string | string[] | undefined; \"sec-websocket-extensions\"?: string | string[] | undefined; \"sec-websocket-key\"?: string | string[] | undefined; \"sec-websocket-protocol\"?: string | string[] | undefined; \"sec-websocket-version\"?: string | string[] | undefined; \"set-cookie\"?: string | string[] | undefined; \"strict-transport-security\"?: string | string[] | undefined; tk?: string | string[] | undefined; trailer?: string | string[] | undefined; \"transfer-encoding\"?: string | string[] | undefined; upgrade?: string | string[] | undefined; \"user-agent\"?: string | string[] | undefined; vary?: string | string[] | undefined; via?: string | string[] | undefined; \"www-authenticate\"?: string | string[] | undefined; } & { [header: string]: string | string[] | undefined; }" + "{ date?: string | string[] | undefined; warning?: string | string[] | undefined; location?: string | string[] | undefined; range?: string | string[] | undefined; from?: string | string[] | undefined; etag?: string | string[] | undefined; accept?: string | string[] | undefined; \"accept-language\"?: string | string[] | undefined; \"accept-patch\"?: string | string[] | undefined; \"accept-ranges\"?: string | string[] | undefined; \"access-control-allow-credentials\"?: string | string[] | undefined; \"access-control-allow-headers\"?: string | string[] | undefined; \"access-control-allow-methods\"?: string | string[] | undefined; \"access-control-allow-origin\"?: string | string[] | undefined; \"access-control-expose-headers\"?: string | string[] | undefined; \"access-control-max-age\"?: string | string[] | undefined; \"access-control-request-headers\"?: string | string[] | undefined; \"access-control-request-method\"?: string | string[] | undefined; age?: string | string[] | undefined; allow?: string | string[] | undefined; \"alt-svc\"?: string | string[] | undefined; authorization?: string | string[] | undefined; \"cache-control\"?: string | string[] | undefined; connection?: string | string[] | undefined; \"content-disposition\"?: string | string[] | undefined; \"content-encoding\"?: string | string[] | undefined; \"content-language\"?: string | string[] | undefined; \"content-length\"?: string | string[] | undefined; \"content-location\"?: string | string[] | undefined; \"content-range\"?: string | string[] | undefined; \"content-type\"?: string | string[] | undefined; cookie?: string | string[] | undefined; expect?: string | string[] | undefined; expires?: string | string[] | undefined; forwarded?: string | string[] | undefined; host?: string | string[] | undefined; \"if-match\"?: string | string[] | undefined; \"if-modified-since\"?: string | string[] | undefined; \"if-none-match\"?: string | string[] | undefined; \"if-unmodified-since\"?: string | string[] | undefined; \"last-modified\"?: string | string[] | undefined; origin?: string | string[] | undefined; pragma?: string | string[] | undefined; \"proxy-authenticate\"?: string | string[] | undefined; \"proxy-authorization\"?: string | string[] | undefined; \"public-key-pins\"?: string | string[] | undefined; referer?: string | string[] | undefined; \"retry-after\"?: string | string[] | undefined; \"sec-websocket-accept\"?: string | string[] | undefined; \"sec-websocket-extensions\"?: string | string[] | undefined; \"sec-websocket-key\"?: string | string[] | undefined; \"sec-websocket-protocol\"?: string | string[] | undefined; \"sec-websocket-version\"?: string | string[] | undefined; \"set-cookie\"?: string | string[] | undefined; \"strict-transport-security\"?: string | string[] | undefined; tk?: string | string[] | undefined; trailer?: string | string[] | undefined; \"transfer-encoding\"?: string | string[] | undefined; upgrade?: string | string[] | undefined; \"user-agent\"?: string | string[] | undefined; vary?: string | string[] | undefined; via?: string | string[] | undefined; \"www-authenticate\"?: string | string[] | undefined; } & { [header: string]: string | string[] | undefined; }" ], "path": "packages/core/http/core-http-server/src/router/headers.ts", "deprecated": false, @@ -16248,7 +16248,7 @@ "\nSet of well-known HTTP headers." ], "signature": [ - "\"date\" | \"warning\" | \"range\" | \"from\" | \"etag\" | \"accept\" | \"accept-language\" | \"accept-patch\" | \"accept-ranges\" | \"access-control-allow-credentials\" | \"access-control-allow-headers\" | \"access-control-allow-methods\" | \"access-control-allow-origin\" | \"access-control-expose-headers\" | \"access-control-max-age\" | \"access-control-request-headers\" | \"access-control-request-method\" | \"age\" | \"allow\" | \"alt-svc\" | \"authorization\" | \"cache-control\" | \"connection\" | \"content-disposition\" | \"content-encoding\" | \"content-language\" | \"content-length\" | \"content-location\" | \"content-range\" | \"content-type\" | \"cookie\" | \"expect\" | \"expires\" | \"forwarded\" | \"host\" | \"if-match\" | \"if-modified-since\" | \"if-none-match\" | \"if-unmodified-since\" | \"last-modified\" | \"location\" | \"origin\" | \"pragma\" | \"proxy-authenticate\" | \"proxy-authorization\" | \"public-key-pins\" | \"referer\" | \"retry-after\" | \"sec-websocket-accept\" | \"sec-websocket-extensions\" | \"sec-websocket-key\" | \"sec-websocket-protocol\" | \"sec-websocket-version\" | \"set-cookie\" | \"strict-transport-security\" | \"tk\" | \"trailer\" | \"transfer-encoding\" | \"upgrade\" | \"user-agent\" | \"vary\" | \"via\" | \"www-authenticate\"" + "\"date\" | \"warning\" | \"location\" | \"range\" | \"from\" | \"etag\" | \"accept\" | \"accept-language\" | \"accept-patch\" | \"accept-ranges\" | \"access-control-allow-credentials\" | \"access-control-allow-headers\" | \"access-control-allow-methods\" | \"access-control-allow-origin\" | \"access-control-expose-headers\" | \"access-control-max-age\" | \"access-control-request-headers\" | \"access-control-request-method\" | \"age\" | \"allow\" | \"alt-svc\" | \"authorization\" | \"cache-control\" | \"connection\" | \"content-disposition\" | \"content-encoding\" | \"content-language\" | \"content-length\" | \"content-location\" | \"content-range\" | \"content-type\" | \"cookie\" | \"expect\" | \"expires\" | \"forwarded\" | \"host\" | \"if-match\" | \"if-modified-since\" | \"if-none-match\" | \"if-unmodified-since\" | \"last-modified\" | \"origin\" | \"pragma\" | \"proxy-authenticate\" | \"proxy-authorization\" | \"public-key-pins\" | \"referer\" | \"retry-after\" | \"sec-websocket-accept\" | \"sec-websocket-extensions\" | \"sec-websocket-key\" | \"sec-websocket-protocol\" | \"sec-websocket-version\" | \"set-cookie\" | \"strict-transport-security\" | \"tk\" | \"trailer\" | \"transfer-encoding\" | \"upgrade\" | \"user-agent\" | \"vary\" | \"via\" | \"www-authenticate\"" ], "path": "packages/core/http/core-http-server/src/router/headers.ts", "deprecated": false, @@ -17354,7 +17354,7 @@ "\nHttp response headers to set." ], "signature": [ - "Record | Record<\"date\" | \"warning\" | \"range\" | \"from\" | \"etag\" | \"accept\" | \"accept-language\" | \"accept-patch\" | \"accept-ranges\" | \"access-control-allow-credentials\" | \"access-control-allow-headers\" | \"access-control-allow-methods\" | \"access-control-allow-origin\" | \"access-control-expose-headers\" | \"access-control-max-age\" | \"access-control-request-headers\" | \"access-control-request-method\" | \"age\" | \"allow\" | \"alt-svc\" | \"authorization\" | \"cache-control\" | \"connection\" | \"content-disposition\" | \"content-encoding\" | \"content-language\" | \"content-length\" | \"content-location\" | \"content-range\" | \"content-type\" | \"cookie\" | \"expect\" | \"expires\" | \"forwarded\" | \"host\" | \"if-match\" | \"if-modified-since\" | \"if-none-match\" | \"if-unmodified-since\" | \"last-modified\" | \"location\" | \"origin\" | \"pragma\" | \"proxy-authenticate\" | \"proxy-authorization\" | \"public-key-pins\" | \"referer\" | \"retry-after\" | \"sec-websocket-accept\" | \"sec-websocket-extensions\" | \"sec-websocket-key\" | \"sec-websocket-protocol\" | \"sec-websocket-version\" | \"set-cookie\" | \"strict-transport-security\" | \"tk\" | \"trailer\" | \"transfer-encoding\" | \"upgrade\" | \"user-agent\" | \"vary\" | \"via\" | \"www-authenticate\", string | string[]>" + "Record | Record<\"date\" | \"warning\" | \"location\" | \"range\" | \"from\" | \"etag\" | \"accept\" | \"accept-language\" | \"accept-patch\" | \"accept-ranges\" | \"access-control-allow-credentials\" | \"access-control-allow-headers\" | \"access-control-allow-methods\" | \"access-control-allow-origin\" | \"access-control-expose-headers\" | \"access-control-max-age\" | \"access-control-request-headers\" | \"access-control-request-method\" | \"age\" | \"allow\" | \"alt-svc\" | \"authorization\" | \"cache-control\" | \"connection\" | \"content-disposition\" | \"content-encoding\" | \"content-language\" | \"content-length\" | \"content-location\" | \"content-range\" | \"content-type\" | \"cookie\" | \"expect\" | \"expires\" | \"forwarded\" | \"host\" | \"if-match\" | \"if-modified-since\" | \"if-none-match\" | \"if-unmodified-since\" | \"last-modified\" | \"origin\" | \"pragma\" | \"proxy-authenticate\" | \"proxy-authorization\" | \"public-key-pins\" | \"referer\" | \"retry-after\" | \"sec-websocket-accept\" | \"sec-websocket-extensions\" | \"sec-websocket-key\" | \"sec-websocket-protocol\" | \"sec-websocket-version\" | \"set-cookie\" | \"strict-transport-security\" | \"tk\" | \"trailer\" | \"transfer-encoding\" | \"upgrade\" | \"user-agent\" | \"vary\" | \"via\" | \"www-authenticate\", string | string[]>" ], "path": "packages/core/http/core-http-server/src/router/headers.ts", "deprecated": false, diff --git a/api_docs/kbn_core_http_server.mdx b/api_docs/kbn_core_http_server.mdx index 2bad6b3cc6fba..69ec0d058df74 100644 --- a/api_docs/kbn_core_http_server.mdx +++ b/api_docs/kbn_core_http_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-server title: "@kbn/core-http-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-server plugin -date: 2023-11-14 +date: 2023-11-16 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 6c4230791bee0..c73351b576d2d 100644 --- a/api_docs/kbn_core_http_server_internal.mdx +++ b/api_docs/kbn_core_http_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-server-internal title: "@kbn/core-http-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-server-internal plugin -date: 2023-11-14 +date: 2023-11-16 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 a6b7c0e439195..e70fdddbe69f8 100644 --- a/api_docs/kbn_core_http_server_mocks.mdx +++ b/api_docs/kbn_core_http_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-server-mocks title: "@kbn/core-http-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-server-mocks plugin -date: 2023-11-14 +date: 2023-11-16 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 963cfad43300c..9305b77d9d696 100644 --- a/api_docs/kbn_core_i18n_browser.mdx +++ b/api_docs/kbn_core_i18n_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-i18n-browser title: "@kbn/core-i18n-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-i18n-browser plugin -date: 2023-11-14 +date: 2023-11-16 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 398eb3df3a29f..8e30a9928bc7a 100644 --- a/api_docs/kbn_core_i18n_browser_mocks.mdx +++ b/api_docs/kbn_core_i18n_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-i18n-browser-mocks title: "@kbn/core-i18n-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-i18n-browser-mocks plugin -date: 2023-11-14 +date: 2023-11-16 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 6ddf65eb08271..d88e0e3a32c04 100644 --- a/api_docs/kbn_core_i18n_server.mdx +++ b/api_docs/kbn_core_i18n_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-i18n-server title: "@kbn/core-i18n-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-i18n-server plugin -date: 2023-11-14 +date: 2023-11-16 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 dcfafc7b763ec..67a0105427b18 100644 --- a/api_docs/kbn_core_i18n_server_internal.mdx +++ b/api_docs/kbn_core_i18n_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-i18n-server-internal title: "@kbn/core-i18n-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-i18n-server-internal plugin -date: 2023-11-14 +date: 2023-11-16 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 21658d686a6d1..27634b6d7d8e7 100644 --- a/api_docs/kbn_core_i18n_server_mocks.mdx +++ b/api_docs/kbn_core_i18n_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-i18n-server-mocks title: "@kbn/core-i18n-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-i18n-server-mocks plugin -date: 2023-11-14 +date: 2023-11-16 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 a09bc53fea5ea..8e96dd1593f0a 100644 --- a/api_docs/kbn_core_injected_metadata_browser_mocks.mdx +++ b/api_docs/kbn_core_injected_metadata_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-injected-metadata-browser-mocks title: "@kbn/core-injected-metadata-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-injected-metadata-browser-mocks plugin -date: 2023-11-14 +date: 2023-11-16 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 754f37c0d8733..dd835c6f2488f 100644 --- a/api_docs/kbn_core_integrations_browser_internal.mdx +++ b/api_docs/kbn_core_integrations_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-integrations-browser-internal title: "@kbn/core-integrations-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-integrations-browser-internal plugin -date: 2023-11-14 +date: 2023-11-16 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 89cd7f72286df..855e4b70b0985 100644 --- a/api_docs/kbn_core_integrations_browser_mocks.mdx +++ b/api_docs/kbn_core_integrations_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-integrations-browser-mocks title: "@kbn/core-integrations-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-integrations-browser-mocks plugin -date: 2023-11-14 +date: 2023-11-16 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 d41c4f3f7f2f5..3ff751bc15f56 100644 --- a/api_docs/kbn_core_lifecycle_browser.mdx +++ b/api_docs/kbn_core_lifecycle_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-lifecycle-browser title: "@kbn/core-lifecycle-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-lifecycle-browser plugin -date: 2023-11-14 +date: 2023-11-16 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 302d15c2947d9..9a3054fca09e7 100644 --- a/api_docs/kbn_core_lifecycle_browser_mocks.mdx +++ b/api_docs/kbn_core_lifecycle_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-lifecycle-browser-mocks title: "@kbn/core-lifecycle-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-lifecycle-browser-mocks plugin -date: 2023-11-14 +date: 2023-11-16 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 2b6861f82d25e..35bf496984fda 100644 --- a/api_docs/kbn_core_lifecycle_server.mdx +++ b/api_docs/kbn_core_lifecycle_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-lifecycle-server title: "@kbn/core-lifecycle-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-lifecycle-server plugin -date: 2023-11-14 +date: 2023-11-16 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 c7d3452c5c796..698f2f3105d2c 100644 --- a/api_docs/kbn_core_lifecycle_server_mocks.mdx +++ b/api_docs/kbn_core_lifecycle_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-lifecycle-server-mocks title: "@kbn/core-lifecycle-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-lifecycle-server-mocks plugin -date: 2023-11-14 +date: 2023-11-16 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 24f974116752c..a328d5c73083f 100644 --- a/api_docs/kbn_core_logging_browser_mocks.mdx +++ b/api_docs/kbn_core_logging_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-logging-browser-mocks title: "@kbn/core-logging-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-logging-browser-mocks plugin -date: 2023-11-14 +date: 2023-11-16 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 7726d71443efd..c77747874f4e5 100644 --- a/api_docs/kbn_core_logging_common_internal.mdx +++ b/api_docs/kbn_core_logging_common_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-logging-common-internal title: "@kbn/core-logging-common-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-logging-common-internal plugin -date: 2023-11-14 +date: 2023-11-16 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 3428aefc1e938..96261df56bc85 100644 --- a/api_docs/kbn_core_logging_server.mdx +++ b/api_docs/kbn_core_logging_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-logging-server title: "@kbn/core-logging-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-logging-server plugin -date: 2023-11-14 +date: 2023-11-16 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 f3ca9c244b5d0..1a5bd3676d53a 100644 --- a/api_docs/kbn_core_logging_server_internal.mdx +++ b/api_docs/kbn_core_logging_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-logging-server-internal title: "@kbn/core-logging-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-logging-server-internal plugin -date: 2023-11-14 +date: 2023-11-16 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 7c051fbaf8e86..700a2f0444662 100644 --- a/api_docs/kbn_core_logging_server_mocks.mdx +++ b/api_docs/kbn_core_logging_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-logging-server-mocks title: "@kbn/core-logging-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-logging-server-mocks plugin -date: 2023-11-14 +date: 2023-11-16 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 586ac026d5a3c..21fffacb7a025 100644 --- a/api_docs/kbn_core_metrics_collectors_server_internal.mdx +++ b/api_docs/kbn_core_metrics_collectors_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-metrics-collectors-server-internal title: "@kbn/core-metrics-collectors-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-metrics-collectors-server-internal plugin -date: 2023-11-14 +date: 2023-11-16 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 a085fc978646e..9d50d48dd9b91 100644 --- a/api_docs/kbn_core_metrics_collectors_server_mocks.mdx +++ b/api_docs/kbn_core_metrics_collectors_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-metrics-collectors-server-mocks title: "@kbn/core-metrics-collectors-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-metrics-collectors-server-mocks plugin -date: 2023-11-14 +date: 2023-11-16 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 fe11703a9ec2f..90d40160bdd60 100644 --- a/api_docs/kbn_core_metrics_server.mdx +++ b/api_docs/kbn_core_metrics_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-metrics-server title: "@kbn/core-metrics-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-metrics-server plugin -date: 2023-11-14 +date: 2023-11-16 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 71ec2f38e8f5a..fcb251894033d 100644 --- a/api_docs/kbn_core_metrics_server_internal.mdx +++ b/api_docs/kbn_core_metrics_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-metrics-server-internal title: "@kbn/core-metrics-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-metrics-server-internal plugin -date: 2023-11-14 +date: 2023-11-16 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 a53a2205cc8a8..648476b471d7b 100644 --- a/api_docs/kbn_core_metrics_server_mocks.mdx +++ b/api_docs/kbn_core_metrics_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-metrics-server-mocks title: "@kbn/core-metrics-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-metrics-server-mocks plugin -date: 2023-11-14 +date: 2023-11-16 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 cf4bae12ece0e..d64bea6e8ceb2 100644 --- a/api_docs/kbn_core_mount_utils_browser.mdx +++ b/api_docs/kbn_core_mount_utils_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-mount-utils-browser title: "@kbn/core-mount-utils-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-mount-utils-browser plugin -date: 2023-11-14 +date: 2023-11-16 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 d4585bd9d010f..64fb1e71ad526 100644 --- a/api_docs/kbn_core_node_server.mdx +++ b/api_docs/kbn_core_node_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-node-server title: "@kbn/core-node-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-node-server plugin -date: 2023-11-14 +date: 2023-11-16 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 656b8a6632c63..70776e7f01710 100644 --- a/api_docs/kbn_core_node_server_internal.mdx +++ b/api_docs/kbn_core_node_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-node-server-internal title: "@kbn/core-node-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-node-server-internal plugin -date: 2023-11-14 +date: 2023-11-16 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 4aff43c6e30a5..326e2fd1a347d 100644 --- a/api_docs/kbn_core_node_server_mocks.mdx +++ b/api_docs/kbn_core_node_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-node-server-mocks title: "@kbn/core-node-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-node-server-mocks plugin -date: 2023-11-14 +date: 2023-11-16 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 574c26851c909..4c274ad815872 100644 --- a/api_docs/kbn_core_notifications_browser.mdx +++ b/api_docs/kbn_core_notifications_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-notifications-browser title: "@kbn/core-notifications-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-notifications-browser plugin -date: 2023-11-14 +date: 2023-11-16 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 596ae4c74aa68..f224b2f42c617 100644 --- a/api_docs/kbn_core_notifications_browser_internal.mdx +++ b/api_docs/kbn_core_notifications_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-notifications-browser-internal title: "@kbn/core-notifications-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-notifications-browser-internal plugin -date: 2023-11-14 +date: 2023-11-16 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 7e000b5ff27d0..295f912277225 100644 --- a/api_docs/kbn_core_notifications_browser_mocks.mdx +++ b/api_docs/kbn_core_notifications_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-notifications-browser-mocks title: "@kbn/core-notifications-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-notifications-browser-mocks plugin -date: 2023-11-14 +date: 2023-11-16 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 14d9728d062d8..970addfac64d1 100644 --- a/api_docs/kbn_core_overlays_browser.mdx +++ b/api_docs/kbn_core_overlays_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-overlays-browser title: "@kbn/core-overlays-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-overlays-browser plugin -date: 2023-11-14 +date: 2023-11-16 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 42d54edae6265..a46d760d36982 100644 --- a/api_docs/kbn_core_overlays_browser_internal.mdx +++ b/api_docs/kbn_core_overlays_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-overlays-browser-internal title: "@kbn/core-overlays-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-overlays-browser-internal plugin -date: 2023-11-14 +date: 2023-11-16 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 910f5aae1c19d..74169fb6b52f9 100644 --- a/api_docs/kbn_core_overlays_browser_mocks.mdx +++ b/api_docs/kbn_core_overlays_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-overlays-browser-mocks title: "@kbn/core-overlays-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-overlays-browser-mocks plugin -date: 2023-11-14 +date: 2023-11-16 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 9ae0c83c2668e..0ac7db1caa86c 100644 --- a/api_docs/kbn_core_plugins_browser.mdx +++ b/api_docs/kbn_core_plugins_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-plugins-browser title: "@kbn/core-plugins-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-plugins-browser plugin -date: 2023-11-14 +date: 2023-11-16 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 569e4c72dc5a4..0f12ec12987fa 100644 --- a/api_docs/kbn_core_plugins_browser_mocks.mdx +++ b/api_docs/kbn_core_plugins_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-plugins-browser-mocks title: "@kbn/core-plugins-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-plugins-browser-mocks plugin -date: 2023-11-14 +date: 2023-11-16 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 7f9f7fdd873a3..3cc884220fde5 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: 2023-11-14 +date: 2023-11-16 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 46e203fea0b86..ba98fb28ee933 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: 2023-11-14 +date: 2023-11-16 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.devdocs.json b/api_docs/kbn_core_plugins_server.devdocs.json index 6de41df4a25aa..4a254538d5052 100644 --- a/api_docs/kbn_core_plugins_server.devdocs.json +++ b/api_docs/kbn_core_plugins_server.devdocs.json @@ -1222,7 +1222,7 @@ "section": "def-common.PluginInitializerContext", "text": "PluginInitializerContext" }, - ") => ", + ") => Promise<", { "pluginId": "@kbn/core-plugins-server", "scope": "common", @@ -1246,7 +1246,7 @@ "section": "def-common.AsyncPlugin", "text": "AsyncPlugin" }, - "" + ">" ], "path": "packages/core/plugins/core-plugins-server/src/types.ts", "deprecated": false, diff --git a/api_docs/kbn_core_plugins_server.mdx b/api_docs/kbn_core_plugins_server.mdx index efed384eddf76..8dd6ec1f0070e 100644 --- a/api_docs/kbn_core_plugins_server.mdx +++ b/api_docs/kbn_core_plugins_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-plugins-server title: "@kbn/core-plugins-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-plugins-server plugin -date: 2023-11-14 +date: 2023-11-16 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 22405e9c27c1d..2e161fa2396ef 100644 --- a/api_docs/kbn_core_plugins_server_mocks.mdx +++ b/api_docs/kbn_core_plugins_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-plugins-server-mocks title: "@kbn/core-plugins-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-plugins-server-mocks plugin -date: 2023-11-14 +date: 2023-11-16 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 3d83be39bf110..76b4ce950ac39 100644 --- a/api_docs/kbn_core_preboot_server.mdx +++ b/api_docs/kbn_core_preboot_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-preboot-server title: "@kbn/core-preboot-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-preboot-server plugin -date: 2023-11-14 +date: 2023-11-16 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 c35a06d2fc8ba..4da0a4add6f7f 100644 --- a/api_docs/kbn_core_preboot_server_mocks.mdx +++ b/api_docs/kbn_core_preboot_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-preboot-server-mocks title: "@kbn/core-preboot-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-preboot-server-mocks plugin -date: 2023-11-14 +date: 2023-11-16 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 5bc4151e83dbb..611f8deaddb62 100644 --- a/api_docs/kbn_core_rendering_browser_mocks.mdx +++ b/api_docs/kbn_core_rendering_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-rendering-browser-mocks title: "@kbn/core-rendering-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-rendering-browser-mocks plugin -date: 2023-11-14 +date: 2023-11-16 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 a50d342007b51..24702fd09bd5c 100644 --- a/api_docs/kbn_core_rendering_server_internal.mdx +++ b/api_docs/kbn_core_rendering_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-rendering-server-internal title: "@kbn/core-rendering-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-rendering-server-internal plugin -date: 2023-11-14 +date: 2023-11-16 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 e923108ca3e08..be52019337cf2 100644 --- a/api_docs/kbn_core_rendering_server_mocks.mdx +++ b/api_docs/kbn_core_rendering_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-rendering-server-mocks title: "@kbn/core-rendering-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-rendering-server-mocks plugin -date: 2023-11-14 +date: 2023-11-16 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 b6ec45ab218fd..30381c53066bd 100644 --- a/api_docs/kbn_core_root_server_internal.mdx +++ b/api_docs/kbn_core_root_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-root-server-internal title: "@kbn/core-root-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-root-server-internal plugin -date: 2023-11-14 +date: 2023-11-16 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 3343bb51e567f..b8d9b047e9fc2 100644 --- a/api_docs/kbn_core_saved_objects_api_browser.mdx +++ b/api_docs/kbn_core_saved_objects_api_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-api-browser title: "@kbn/core-saved-objects-api-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-api-browser plugin -date: 2023-11-14 +date: 2023-11-16 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 7d7efe503f9fc..80903bbc0c714 100644 --- a/api_docs/kbn_core_saved_objects_api_server.mdx +++ b/api_docs/kbn_core_saved_objects_api_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-api-server title: "@kbn/core-saved-objects-api-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-api-server plugin -date: 2023-11-14 +date: 2023-11-16 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 d766cee298d48..735f71ed70953 100644 --- a/api_docs/kbn_core_saved_objects_api_server_mocks.mdx +++ b/api_docs/kbn_core_saved_objects_api_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-api-server-mocks title: "@kbn/core-saved-objects-api-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-api-server-mocks plugin -date: 2023-11-14 +date: 2023-11-16 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 98618d49cf666..5a4cfdbcabdf5 100644 --- a/api_docs/kbn_core_saved_objects_base_server_internal.mdx +++ b/api_docs/kbn_core_saved_objects_base_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-base-server-internal title: "@kbn/core-saved-objects-base-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-base-server-internal plugin -date: 2023-11-14 +date: 2023-11-16 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 aca9eb5f819e8..edb1dda31a9f2 100644 --- a/api_docs/kbn_core_saved_objects_base_server_mocks.mdx +++ b/api_docs/kbn_core_saved_objects_base_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-base-server-mocks title: "@kbn/core-saved-objects-base-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-base-server-mocks plugin -date: 2023-11-14 +date: 2023-11-16 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 619284a873102..3c2235d8b525e 100644 --- a/api_docs/kbn_core_saved_objects_browser.mdx +++ b/api_docs/kbn_core_saved_objects_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-browser title: "@kbn/core-saved-objects-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-browser plugin -date: 2023-11-14 +date: 2023-11-16 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 29e513d9fdede..e92be68f2c60c 100644 --- a/api_docs/kbn_core_saved_objects_browser_internal.mdx +++ b/api_docs/kbn_core_saved_objects_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-browser-internal title: "@kbn/core-saved-objects-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-browser-internal plugin -date: 2023-11-14 +date: 2023-11-16 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 2e3d732f68a93..444409eceaf98 100644 --- a/api_docs/kbn_core_saved_objects_browser_mocks.mdx +++ b/api_docs/kbn_core_saved_objects_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-browser-mocks title: "@kbn/core-saved-objects-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-browser-mocks plugin -date: 2023-11-14 +date: 2023-11-16 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 91e0ac1c5690d..9c58104676a71 100644 --- a/api_docs/kbn_core_saved_objects_common.mdx +++ b/api_docs/kbn_core_saved_objects_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-common title: "@kbn/core-saved-objects-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-common plugin -date: 2023-11-14 +date: 2023-11-16 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 7dfe387a7cbef..17fa146e01bf1 100644 --- a/api_docs/kbn_core_saved_objects_import_export_server_internal.mdx +++ b/api_docs/kbn_core_saved_objects_import_export_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-import-export-server-internal title: "@kbn/core-saved-objects-import-export-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-import-export-server-internal plugin -date: 2023-11-14 +date: 2023-11-16 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 ef6a31afc69de..cb1c421f73361 100644 --- a/api_docs/kbn_core_saved_objects_import_export_server_mocks.mdx +++ b/api_docs/kbn_core_saved_objects_import_export_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-import-export-server-mocks title: "@kbn/core-saved-objects-import-export-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-import-export-server-mocks plugin -date: 2023-11-14 +date: 2023-11-16 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 3b427a12db0b3..c6a2df2bdfb81 100644 --- a/api_docs/kbn_core_saved_objects_migration_server_internal.mdx +++ b/api_docs/kbn_core_saved_objects_migration_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-migration-server-internal title: "@kbn/core-saved-objects-migration-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-migration-server-internal plugin -date: 2023-11-14 +date: 2023-11-16 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 21aac474fcd30..ba4476ba76971 100644 --- a/api_docs/kbn_core_saved_objects_migration_server_mocks.mdx +++ b/api_docs/kbn_core_saved_objects_migration_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-migration-server-mocks title: "@kbn/core-saved-objects-migration-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-migration-server-mocks plugin -date: 2023-11-14 +date: 2023-11-16 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 80111559a76b7..00ce80eec7f77 100644 --- a/api_docs/kbn_core_saved_objects_server.mdx +++ b/api_docs/kbn_core_saved_objects_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-server title: "@kbn/core-saved-objects-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-server plugin -date: 2023-11-14 +date: 2023-11-16 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 51be9585c2370..094fb5682e9ec 100644 --- a/api_docs/kbn_core_saved_objects_server_internal.mdx +++ b/api_docs/kbn_core_saved_objects_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-server-internal title: "@kbn/core-saved-objects-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-server-internal plugin -date: 2023-11-14 +date: 2023-11-16 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 466e14e717a57..4b3b2779f9119 100644 --- a/api_docs/kbn_core_saved_objects_server_mocks.mdx +++ b/api_docs/kbn_core_saved_objects_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-server-mocks title: "@kbn/core-saved-objects-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-server-mocks plugin -date: 2023-11-14 +date: 2023-11-16 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 5b314d21ca1fb..c564ca08a048d 100644 --- a/api_docs/kbn_core_saved_objects_utils_server.mdx +++ b/api_docs/kbn_core_saved_objects_utils_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-utils-server title: "@kbn/core-saved-objects-utils-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-utils-server plugin -date: 2023-11-14 +date: 2023-11-16 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-utils-server'] --- import kbnCoreSavedObjectsUtilsServerObj from './kbn_core_saved_objects_utils_server.devdocs.json'; diff --git a/api_docs/kbn_core_status_common.mdx b/api_docs/kbn_core_status_common.mdx index 931add2ceab9c..6721891c631ab 100644 --- a/api_docs/kbn_core_status_common.mdx +++ b/api_docs/kbn_core_status_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-status-common title: "@kbn/core-status-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-status-common plugin -date: 2023-11-14 +date: 2023-11-16 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 154deb39c39ee..af18c864dafd0 100644 --- a/api_docs/kbn_core_status_common_internal.mdx +++ b/api_docs/kbn_core_status_common_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-status-common-internal title: "@kbn/core-status-common-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-status-common-internal plugin -date: 2023-11-14 +date: 2023-11-16 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 11ab31d5ef3d9..25887ac55df6d 100644 --- a/api_docs/kbn_core_status_server.mdx +++ b/api_docs/kbn_core_status_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-status-server title: "@kbn/core-status-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-status-server plugin -date: 2023-11-14 +date: 2023-11-16 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 56df176d90ed6..abd13b6e9436b 100644 --- a/api_docs/kbn_core_status_server_internal.mdx +++ b/api_docs/kbn_core_status_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-status-server-internal title: "@kbn/core-status-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-status-server-internal plugin -date: 2023-11-14 +date: 2023-11-16 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 082190c1def71..93a8f6300d55e 100644 --- a/api_docs/kbn_core_status_server_mocks.mdx +++ b/api_docs/kbn_core_status_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-status-server-mocks title: "@kbn/core-status-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-status-server-mocks plugin -date: 2023-11-14 +date: 2023-11-16 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 81beb11ce626d..7fd05afebd092 100644 --- a/api_docs/kbn_core_test_helpers_deprecations_getters.mdx +++ b/api_docs/kbn_core_test_helpers_deprecations_getters.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-test-helpers-deprecations-getters title: "@kbn/core-test-helpers-deprecations-getters" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-test-helpers-deprecations-getters plugin -date: 2023-11-14 +date: 2023-11-16 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 dbbd2eca2e56a..4b3175e691341 100644 --- a/api_docs/kbn_core_test_helpers_http_setup_browser.mdx +++ b/api_docs/kbn_core_test_helpers_http_setup_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-test-helpers-http-setup-browser title: "@kbn/core-test-helpers-http-setup-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-test-helpers-http-setup-browser plugin -date: 2023-11-14 +date: 2023-11-16 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 71887ddfee177..c0efbacdd0bb1 100644 --- a/api_docs/kbn_core_test_helpers_kbn_server.mdx +++ b/api_docs/kbn_core_test_helpers_kbn_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-test-helpers-kbn-server title: "@kbn/core-test-helpers-kbn-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-test-helpers-kbn-server plugin -date: 2023-11-14 +date: 2023-11-16 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 60396b7dd0758..fcfabc7d2b9db 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: 2023-11-14 +date: 2023-11-16 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 cd8895353eac4..0761d79e0d95e 100644 --- a/api_docs/kbn_core_test_helpers_so_type_serializer.mdx +++ b/api_docs/kbn_core_test_helpers_so_type_serializer.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-test-helpers-so-type-serializer title: "@kbn/core-test-helpers-so-type-serializer" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-test-helpers-so-type-serializer plugin -date: 2023-11-14 +date: 2023-11-16 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 31bca2cb8f125..8743138f0298a 100644 --- a/api_docs/kbn_core_test_helpers_test_utils.mdx +++ b/api_docs/kbn_core_test_helpers_test_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-test-helpers-test-utils title: "@kbn/core-test-helpers-test-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-test-helpers-test-utils plugin -date: 2023-11-14 +date: 2023-11-16 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 fa3e134de0507..444d0a84a8df7 100644 --- a/api_docs/kbn_core_theme_browser.mdx +++ b/api_docs/kbn_core_theme_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-theme-browser title: "@kbn/core-theme-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-theme-browser plugin -date: 2023-11-14 +date: 2023-11-16 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 13ec1125bea00..adc8eb15e68ea 100644 --- a/api_docs/kbn_core_theme_browser_mocks.mdx +++ b/api_docs/kbn_core_theme_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-theme-browser-mocks title: "@kbn/core-theme-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-theme-browser-mocks plugin -date: 2023-11-14 +date: 2023-11-16 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 93663a97a5565..fc5b8e1a44ae1 100644 --- a/api_docs/kbn_core_ui_settings_browser.mdx +++ b/api_docs/kbn_core_ui_settings_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-ui-settings-browser title: "@kbn/core-ui-settings-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-ui-settings-browser plugin -date: 2023-11-14 +date: 2023-11-16 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 858d45d5eac76..4717d5b705d39 100644 --- a/api_docs/kbn_core_ui_settings_browser_internal.mdx +++ b/api_docs/kbn_core_ui_settings_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-ui-settings-browser-internal title: "@kbn/core-ui-settings-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-ui-settings-browser-internal plugin -date: 2023-11-14 +date: 2023-11-16 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 dc02ca34ef3f9..0132060ef647c 100644 --- a/api_docs/kbn_core_ui_settings_browser_mocks.mdx +++ b/api_docs/kbn_core_ui_settings_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-ui-settings-browser-mocks title: "@kbn/core-ui-settings-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-ui-settings-browser-mocks plugin -date: 2023-11-14 +date: 2023-11-16 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 bbd44b94503c2..051290535f759 100644 --- a/api_docs/kbn_core_ui_settings_common.mdx +++ b/api_docs/kbn_core_ui_settings_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-ui-settings-common title: "@kbn/core-ui-settings-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-ui-settings-common plugin -date: 2023-11-14 +date: 2023-11-16 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 8037d1c9554df..b226da910d714 100644 --- a/api_docs/kbn_core_ui_settings_server.mdx +++ b/api_docs/kbn_core_ui_settings_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-ui-settings-server title: "@kbn/core-ui-settings-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-ui-settings-server plugin -date: 2023-11-14 +date: 2023-11-16 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 49f64e7bc387d..a07743c906bbe 100644 --- a/api_docs/kbn_core_ui_settings_server_internal.mdx +++ b/api_docs/kbn_core_ui_settings_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-ui-settings-server-internal title: "@kbn/core-ui-settings-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-ui-settings-server-internal plugin -date: 2023-11-14 +date: 2023-11-16 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 86fb18fe41525..9d05216df57ff 100644 --- a/api_docs/kbn_core_ui_settings_server_mocks.mdx +++ b/api_docs/kbn_core_ui_settings_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-ui-settings-server-mocks title: "@kbn/core-ui-settings-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-ui-settings-server-mocks plugin -date: 2023-11-14 +date: 2023-11-16 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 a8016a29da441..a7250b6348207 100644 --- a/api_docs/kbn_core_usage_data_server.mdx +++ b/api_docs/kbn_core_usage_data_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-usage-data-server title: "@kbn/core-usage-data-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-usage-data-server plugin -date: 2023-11-14 +date: 2023-11-16 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 80825c14eee22..776bb1b3e2a7c 100644 --- a/api_docs/kbn_core_usage_data_server_internal.mdx +++ b/api_docs/kbn_core_usage_data_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-usage-data-server-internal title: "@kbn/core-usage-data-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-usage-data-server-internal plugin -date: 2023-11-14 +date: 2023-11-16 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 9d432cd70cec8..8382c5d6b080c 100644 --- a/api_docs/kbn_core_usage_data_server_mocks.mdx +++ b/api_docs/kbn_core_usage_data_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-usage-data-server-mocks title: "@kbn/core-usage-data-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-usage-data-server-mocks plugin -date: 2023-11-14 +date: 2023-11-16 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_settings_server.mdx b/api_docs/kbn_core_user_settings_server.mdx index 7f08d79a09a53..6c39b8b24267d 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: 2023-11-14 +date: 2023-11-16 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_internal.mdx b/api_docs/kbn_core_user_settings_server_internal.mdx index a215dbab58a1a..c68e453848d86 100644 --- a/api_docs/kbn_core_user_settings_server_internal.mdx +++ b/api_docs/kbn_core_user_settings_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-user-settings-server-internal title: "@kbn/core-user-settings-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-user-settings-server-internal plugin -date: 2023-11-14 +date: 2023-11-16 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-user-settings-server-internal'] --- import kbnCoreUserSettingsServerInternalObj from './kbn_core_user_settings_server_internal.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 32dbc90c77643..09c71e11eb188 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: 2023-11-14 +date: 2023-11-16 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 7b80493fb466d..8fd8b457f272f 100644 --- a/api_docs/kbn_crypto.mdx +++ b/api_docs/kbn_crypto.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-crypto title: "@kbn/crypto" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/crypto plugin -date: 2023-11-14 +date: 2023-11-16 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 8aae88dec189e..b741fd434c654 100644 --- a/api_docs/kbn_crypto_browser.mdx +++ b/api_docs/kbn_crypto_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-crypto-browser title: "@kbn/crypto-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/crypto-browser plugin -date: 2023-11-14 +date: 2023-11-16 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/crypto-browser'] --- import kbnCryptoBrowserObj from './kbn_crypto_browser.devdocs.json'; diff --git a/api_docs/kbn_custom_integrations.mdx b/api_docs/kbn_custom_integrations.mdx index 16d02e3d8117e..67837181e54f3 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: 2023-11-14 +date: 2023-11-16 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 3c42c59f84265..8e67ef43452c9 100644 --- a/api_docs/kbn_cypress_config.mdx +++ b/api_docs/kbn_cypress_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-cypress-config title: "@kbn/cypress-config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/cypress-config plugin -date: 2023-11-14 +date: 2023-11-16 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/cypress-config'] --- import kbnCypressConfigObj from './kbn_cypress_config.devdocs.json'; diff --git a/api_docs/kbn_data_service.mdx b/api_docs/kbn_data_service.mdx index 1bb0dd85897e5..e95124d51e3d4 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: 2023-11-14 +date: 2023-11-16 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/data-service'] --- import kbnDataServiceObj from './kbn_data_service.devdocs.json'; diff --git a/api_docs/kbn_datemath.mdx b/api_docs/kbn_datemath.mdx index 296f5177bb7d1..8e4ae3ecdfd03 100644 --- a/api_docs/kbn_datemath.mdx +++ b/api_docs/kbn_datemath.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-datemath title: "@kbn/datemath" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/datemath plugin -date: 2023-11-14 +date: 2023-11-16 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 5d27b6fb3ccf0..882b9fda4cf34 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: 2023-11-14 +date: 2023-11-16 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 150aa76bac475..4adaa6eeec308 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: 2023-11-14 +date: 2023-11-16 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/deeplinks-devtools'] --- import kbnDeeplinksDevtoolsObj from './kbn_deeplinks_devtools.devdocs.json'; diff --git a/api_docs/kbn_deeplinks_management.mdx b/api_docs/kbn_deeplinks_management.mdx index ba7d5cfd11fdd..c575cbfbda218 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: 2023-11-14 +date: 2023-11-16 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 b3ac64e0da216..279a828cbe84a 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: 2023-11-14 +date: 2023-11-16 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 7c83f6dc90a64..07c06bd01fe2b 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: 2023-11-14 +date: 2023-11-16 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 117bd0e01a991..bd5117564cbeb 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: 2023-11-14 +date: 2023-11-16 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/deeplinks-search'] --- import kbnDeeplinksSearchObj from './kbn_deeplinks_search.devdocs.json'; diff --git a/api_docs/kbn_default_nav_analytics.mdx b/api_docs/kbn_default_nav_analytics.mdx index 7d6cefc01c361..1cda3dfdf6cc9 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: 2023-11-14 +date: 2023-11-16 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 3d4e8f8e15b08..3878c6f84ee50 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: 2023-11-14 +date: 2023-11-16 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 2c6eb6053bf05..0e79c5c0b93c5 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: 2023-11-14 +date: 2023-11-16 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 2ae63e1f07d4b..2910fa34db36d 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: 2023-11-14 +date: 2023-11-16 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 2452d085c5de2..63b6d26c64f32 100644 --- a/api_docs/kbn_dev_cli_errors.mdx +++ b/api_docs/kbn_dev_cli_errors.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-dev-cli-errors title: "@kbn/dev-cli-errors" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/dev-cli-errors plugin -date: 2023-11-14 +date: 2023-11-16 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 d327b0b1e10a1..3bbf3fa4b50aa 100644 --- a/api_docs/kbn_dev_cli_runner.mdx +++ b/api_docs/kbn_dev_cli_runner.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-dev-cli-runner title: "@kbn/dev-cli-runner" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/dev-cli-runner plugin -date: 2023-11-14 +date: 2023-11-16 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 6d2ce399aacea..c8c3a0bbee67a 100644 --- a/api_docs/kbn_dev_proc_runner.mdx +++ b/api_docs/kbn_dev_proc_runner.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-dev-proc-runner title: "@kbn/dev-proc-runner" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/dev-proc-runner plugin -date: 2023-11-14 +date: 2023-11-16 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 aa86f5b7fe0b0..c2796e378be55 100644 --- a/api_docs/kbn_dev_utils.mdx +++ b/api_docs/kbn_dev_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-dev-utils title: "@kbn/dev-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/dev-utils plugin -date: 2023-11-14 +date: 2023-11-16 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 ad618b2d5e67c..c6fd7cf2abb10 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: 2023-11-14 +date: 2023-11-16 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 c7391407a995a..4c91d4cbee507 100644 --- a/api_docs/kbn_doc_links.devdocs.json +++ b/api_docs/kbn_doc_links.devdocs.json @@ -658,7 +658,7 @@ "label": "observability", "description": [], "signature": [ - "{ readonly guide: string; readonly infrastructureThreshold: string; readonly logsThreshold: string; readonly metricsThreshold: string; readonly threshold: string; readonly monitorStatus: string; readonly monitorUptime: string; readonly tlsCertificate: string; readonly uptimeDurationAnomaly: string; readonly monitorLogs: string; readonly analyzeMetrics: string; readonly monitorUptimeSynthetics: string; readonly userExperience: string; readonly createAlerts: string; readonly syntheticsAlerting: string; readonly syntheticsCommandReference: string; readonly syntheticsProjectMonitors: string; readonly syntheticsMigrateFromIntegration: string; readonly sloBurnRateRule: string; }" + "{ readonly guide: string; readonly infrastructureThreshold: string; readonly logsThreshold: string; readonly metricsThreshold: string; readonly customThreshold: string; readonly monitorStatus: string; readonly monitorUptime: string; readonly tlsCertificate: string; readonly uptimeDurationAnomaly: string; readonly monitorLogs: string; readonly analyzeMetrics: string; readonly monitorUptimeSynthetics: string; readonly userExperience: string; readonly createAlerts: string; readonly syntheticsAlerting: string; readonly syntheticsCommandReference: string; readonly syntheticsProjectMonitors: string; readonly syntheticsMigrateFromIntegration: string; readonly sloBurnRateRule: 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 e8a959719f53f..956715f22011e 100644 --- a/api_docs/kbn_doc_links.mdx +++ b/api_docs/kbn_doc_links.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-doc-links title: "@kbn/doc-links" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/doc-links plugin -date: 2023-11-14 +date: 2023-11-16 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 26c4a69d4b5d6..93ddee1f4b738 100644 --- a/api_docs/kbn_docs_utils.mdx +++ b/api_docs/kbn_docs_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-docs-utils title: "@kbn/docs-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/docs-utils plugin -date: 2023-11-14 +date: 2023-11-16 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 2021a82a688c2..cfca9512a5004 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: 2023-11-14 +date: 2023-11-16 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 445c2d1cf9f0f..e5ea9774fd2f5 100644 --- a/api_docs/kbn_ebt_tools.mdx +++ b/api_docs/kbn_ebt_tools.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ebt-tools title: "@kbn/ebt-tools" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ebt-tools plugin -date: 2023-11-14 +date: 2023-11-16 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ebt-tools'] --- import kbnEbtToolsObj from './kbn_ebt_tools.devdocs.json'; diff --git a/api_docs/kbn_ecs.mdx b/api_docs/kbn_ecs.mdx index f416df2cd72f6..026ece1775d52 100644 --- a/api_docs/kbn_ecs.mdx +++ b/api_docs/kbn_ecs.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ecs title: "@kbn/ecs" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ecs plugin -date: 2023-11-14 +date: 2023-11-16 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ecs'] --- import kbnEcsObj from './kbn_ecs.devdocs.json'; diff --git a/api_docs/kbn_ecs_data_quality_dashboard.mdx b/api_docs/kbn_ecs_data_quality_dashboard.mdx index 2ff0e9c745134..e1eb83ecca662 100644 --- a/api_docs/kbn_ecs_data_quality_dashboard.mdx +++ b/api_docs/kbn_ecs_data_quality_dashboard.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ecs-data-quality-dashboard title: "@kbn/ecs-data-quality-dashboard" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ecs-data-quality-dashboard plugin -date: 2023-11-14 +date: 2023-11-16 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_assistant.mdx b/api_docs/kbn_elastic_assistant.mdx index 8c10f58f59002..5cde4c3ad25eb 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: 2023-11-14 +date: 2023-11-16 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/elastic-assistant'] --- import kbnElasticAssistantObj from './kbn_elastic_assistant.devdocs.json'; diff --git a/api_docs/kbn_es.mdx b/api_docs/kbn_es.mdx index 45cdc9163c00f..19e005519406d 100644 --- a/api_docs/kbn_es.mdx +++ b/api_docs/kbn_es.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-es title: "@kbn/es" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/es plugin -date: 2023-11-14 +date: 2023-11-16 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 c7a89aed23496..feca9bd4bdf1c 100644 --- a/api_docs/kbn_es_archiver.mdx +++ b/api_docs/kbn_es_archiver.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-es-archiver title: "@kbn/es-archiver" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/es-archiver plugin -date: 2023-11-14 +date: 2023-11-16 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 28dbe8fbcb8fe..9abe569c9e6b5 100644 --- a/api_docs/kbn_es_errors.mdx +++ b/api_docs/kbn_es_errors.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-es-errors title: "@kbn/es-errors" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/es-errors plugin -date: 2023-11-14 +date: 2023-11-16 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 57a51c84e11ab..a20beb160dc9d 100644 --- a/api_docs/kbn_es_query.mdx +++ b/api_docs/kbn_es_query.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-es-query title: "@kbn/es-query" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/es-query plugin -date: 2023-11-14 +date: 2023-11-16 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 93846bf169948..5845573fb4ae8 100644 --- a/api_docs/kbn_es_types.mdx +++ b/api_docs/kbn_es_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-es-types title: "@kbn/es-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/es-types plugin -date: 2023-11-14 +date: 2023-11-16 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 ef168958fbc58..366cdec67c8c7 100644 --- a/api_docs/kbn_eslint_plugin_imports.mdx +++ b/api_docs/kbn_eslint_plugin_imports.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-eslint-plugin-imports title: "@kbn/eslint-plugin-imports" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/eslint-plugin-imports plugin -date: 2023-11-14 +date: 2023-11-16 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/eslint-plugin-imports'] --- import kbnEslintPluginImportsObj from './kbn_eslint_plugin_imports.devdocs.json'; diff --git a/api_docs/kbn_event_annotation_common.mdx b/api_docs/kbn_event_annotation_common.mdx index dc42cfadbf1eb..e0d7211513df7 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: 2023-11-14 +date: 2023-11-16 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 80c71ef1bf27a..03d1d494ef0a5 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: 2023-11-14 +date: 2023-11-16 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 76edfc0cfb67e..bca15df2c67bd 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: 2023-11-14 +date: 2023-11-16 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 4b9dc890f58fc..8ee2498fdb00d 100644 --- a/api_docs/kbn_field_types.mdx +++ b/api_docs/kbn_field_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-field-types title: "@kbn/field-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/field-types plugin -date: 2023-11-14 +date: 2023-11-16 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 b67a33bdb7798..aab8071d09c55 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: 2023-11-14 +date: 2023-11-16 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 03ffde2402f4d..b3e0721d84b8e 100644 --- a/api_docs/kbn_find_used_node_modules.mdx +++ b/api_docs/kbn_find_used_node_modules.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-find-used-node-modules title: "@kbn/find-used-node-modules" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/find-used-node-modules plugin -date: 2023-11-14 +date: 2023-11-16 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/find-used-node-modules'] --- import kbnFindUsedNodeModulesObj from './kbn_find_used_node_modules.devdocs.json'; diff --git a/api_docs/kbn_ftr_common_functional_services.mdx b/api_docs/kbn_ftr_common_functional_services.mdx index a5cd8bf4dc802..c6390d89bfdab 100644 --- a/api_docs/kbn_ftr_common_functional_services.mdx +++ b/api_docs/kbn_ftr_common_functional_services.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ftr-common-functional-services title: "@kbn/ftr-common-functional-services" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ftr-common-functional-services plugin -date: 2023-11-14 +date: 2023-11-16 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ftr-common-functional-services'] --- import kbnFtrCommonFunctionalServicesObj from './kbn_ftr_common_functional_services.devdocs.json'; diff --git a/api_docs/kbn_generate.mdx b/api_docs/kbn_generate.mdx index 6c7b196ebe4a7..27ce99c92bc32 100644 --- a/api_docs/kbn_generate.mdx +++ b/api_docs/kbn_generate.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-generate title: "@kbn/generate" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/generate plugin -date: 2023-11-14 +date: 2023-11-16 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 27cb7b78ee828..2a12d265387b3 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: 2023-11-14 +date: 2023-11-16 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.devdocs.json b/api_docs/kbn_generate_csv.devdocs.json index 2b04c8389060c..f776c97bdf55c 100644 --- a/api_docs/kbn_generate_csv.devdocs.json +++ b/api_docs/kbn_generate_csv.devdocs.json @@ -9,18 +9,10 @@ "objects": [] }, "server": { - "classes": [], - "functions": [], - "interfaces": [], - "enums": [], - "misc": [], - "objects": [] - }, - "common": { "classes": [ { "parentPluginId": "@kbn/generate-csv", - "id": "def-common.CsvGenerator", + "id": "def-server.CsvGenerator", "type": "Class", "tags": [], "label": "CsvGenerator", @@ -31,7 +23,7 @@ "children": [ { "parentPluginId": "@kbn/generate-csv", - "id": "def-common.CsvGenerator.Unnamed", + "id": "def-server.CsvGenerator.Unnamed", "type": "Function", "tags": [], "label": "Constructor", @@ -45,20 +37,14 @@ "children": [ { "parentPluginId": "@kbn/generate-csv", - "id": "def-common.CsvGenerator.Unnamed.$1", + "id": "def-server.CsvGenerator.Unnamed.$1", "type": "Object", "tags": [], "label": "job", "description": [], "signature": [ "Omit<", - { - "pluginId": "@kbn/generate-csv-types", - "scope": "common", - "docId": "kibKbnGenerateCsvTypesPluginApi", - "section": "def-common.JobParams", - "text": "JobParams" - }, + "JobParamsCSV", ", \"version\">" ], "path": "packages/kbn-generate-csv/src/generate_csv.ts", @@ -68,19 +54,21 @@ }, { "parentPluginId": "@kbn/generate-csv", - "id": "def-common.CsvGenerator.Unnamed.$2", + "id": "def-server.CsvGenerator.Unnamed.$2", "type": "Object", "tags": [], "label": "config", "description": [], "signature": [ + "Readonly<{} & { scroll: Readonly<{} & { duration: string; size: number; }>; checkForFormulas: boolean; escapeFormulaValues: boolean; enablePanelActionDownload: boolean; maxSizeBytes: number | ", { - "pluginId": "@kbn/generate-csv-types", + "pluginId": "@kbn/config-schema", "scope": "common", - "docId": "kibKbnGenerateCsvTypesPluginApi", - "section": "def-common.CsvConfig", - "text": "CsvConfig" - } + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ByteSizeValue", + "text": "ByteSizeValue" + }, + "; useByteOrderMarkEncoding: boolean; }>" ], "path": "packages/kbn-generate-csv/src/generate_csv.ts", "deprecated": false, @@ -89,7 +77,7 @@ }, { "parentPluginId": "@kbn/generate-csv", - "id": "def-common.CsvGenerator.Unnamed.$3", + "id": "def-server.CsvGenerator.Unnamed.$3", "type": "Object", "tags": [], "label": "clients", @@ -104,7 +92,7 @@ }, { "parentPluginId": "@kbn/generate-csv", - "id": "def-common.CsvGenerator.Unnamed.$4", + "id": "def-server.CsvGenerator.Unnamed.$4", "type": "Object", "tags": [], "label": "dependencies", @@ -119,7 +107,7 @@ }, { "parentPluginId": "@kbn/generate-csv", - "id": "def-common.CsvGenerator.Unnamed.$5", + "id": "def-server.CsvGenerator.Unnamed.$5", "type": "Object", "tags": [], "label": "cancellationToken", @@ -140,7 +128,7 @@ }, { "parentPluginId": "@kbn/generate-csv", - "id": "def-common.CsvGenerator.Unnamed.$6", + "id": "def-server.CsvGenerator.Unnamed.$6", "type": "Object", "tags": [], "label": "logger", @@ -161,7 +149,7 @@ }, { "parentPluginId": "@kbn/generate-csv", - "id": "def-common.CsvGenerator.Unnamed.$7", + "id": "def-server.CsvGenerator.Unnamed.$7", "type": "Object", "tags": [], "label": "stream", @@ -179,20 +167,14 @@ }, { "parentPluginId": "@kbn/generate-csv", - "id": "def-common.CsvGenerator.generateData", + "id": "def-server.CsvGenerator.generateData", "type": "Function", "tags": [], "label": "generateData", "description": [], "signature": [ "() => Promise<", - { - "pluginId": "@kbn/reporting-common", - "scope": "common", - "docId": "kibKbnReportingCommonPluginApi", - "section": "def-common.TaskRunResult", - "text": "TaskRunResult" - }, + "TaskRunResult", ">" ], "path": "packages/kbn-generate-csv/src/generate_csv.ts", @@ -210,5 +192,13 @@ "enums": [], "misc": [], "objects": [] + }, + "common": { + "classes": [], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] } } \ No newline at end of file diff --git a/api_docs/kbn_generate_csv.mdx b/api_docs/kbn_generate_csv.mdx index 34ffba48cd6d6..15f0991bf7e3c 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: 2023-11-14 +date: 2023-11-16 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/generate-csv'] --- import kbnGenerateCsvObj from './kbn_generate_csv.devdocs.json'; @@ -21,10 +21,10 @@ Contact [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sh | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 10 | 0 | 10 | 0 | +| 10 | 0 | 10 | 1 | -## Common +## Server ### Classes - + diff --git a/api_docs/kbn_generate_csv_types.devdocs.json b/api_docs/kbn_generate_csv_types.devdocs.json deleted file mode 100644 index c816650afc29a..0000000000000 --- a/api_docs/kbn_generate_csv_types.devdocs.json +++ /dev/null @@ -1,244 +0,0 @@ -{ - "id": "@kbn/generate-csv-types", - "client": { - "classes": [], - "functions": [], - "interfaces": [], - "enums": [], - "misc": [], - "objects": [] - }, - "server": { - "classes": [], - "functions": [], - "interfaces": [], - "enums": [], - "misc": [], - "objects": [] - }, - "common": { - "classes": [], - "functions": [], - "interfaces": [ - { - "parentPluginId": "@kbn/generate-csv-types", - "id": "def-common.CsvConfig", - "type": "Interface", - "tags": [], - "label": "CsvConfig", - "description": [], - "path": "packages/kbn-generate-csv-types/index.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "@kbn/generate-csv-types", - "id": "def-common.CsvConfig.checkForFormulas", - "type": "boolean", - "tags": [], - "label": "checkForFormulas", - "description": [], - "path": "packages/kbn-generate-csv-types/index.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "@kbn/generate-csv-types", - "id": "def-common.CsvConfig.escapeFormulaValues", - "type": "boolean", - "tags": [], - "label": "escapeFormulaValues", - "description": [], - "path": "packages/kbn-generate-csv-types/index.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "@kbn/generate-csv-types", - "id": "def-common.CsvConfig.maxSizeBytes", - "type": "CompoundType", - "tags": [], - "label": "maxSizeBytes", - "description": [], - "signature": [ - "number | ", - { - "pluginId": "@kbn/config-schema", - "scope": "common", - "docId": "kibKbnConfigSchemaPluginApi", - "section": "def-common.ByteSizeValue", - "text": "ByteSizeValue" - } - ], - "path": "packages/kbn-generate-csv-types/index.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "@kbn/generate-csv-types", - "id": "def-common.CsvConfig.useByteOrderMarkEncoding", - "type": "boolean", - "tags": [], - "label": "useByteOrderMarkEncoding", - "description": [], - "path": "packages/kbn-generate-csv-types/index.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "@kbn/generate-csv-types", - "id": "def-common.CsvConfig.scroll", - "type": "Object", - "tags": [], - "label": "scroll", - "description": [], - "signature": [ - "{ duration: string; size: number; }" - ], - "path": "packages/kbn-generate-csv-types/index.ts", - "deprecated": false, - "trackAdoption": false - } - ], - "initialIsOpen": false - }, - { - "parentPluginId": "@kbn/generate-csv-types", - "id": "def-common.JobParams", - "type": "Interface", - "tags": [], - "label": "JobParams", - "description": [], - "path": "packages/kbn-generate-csv-types/index.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "@kbn/generate-csv-types", - "id": "def-common.JobParams.searchSource", - "type": "Object", - "tags": [], - "label": "searchSource", - "description": [], - "signature": [ - "{ type?: string | undefined; query?: ", - { - "pluginId": "@kbn/es-query", - "scope": "common", - "docId": "kibKbnEsQueryPluginApi", - "section": "def-common.Query", - "text": "Query" - }, - " | ", - { - "pluginId": "@kbn/es-query", - "scope": "common", - "docId": "kibKbnEsQueryPluginApi", - "section": "def-common.AggregateQuery", - "text": "AggregateQuery" - }, - " | undefined; filter?: ", - { - "pluginId": "@kbn/es-query", - "scope": "common", - "docId": "kibKbnEsQueryPluginApi", - "section": "def-common.Filter", - "text": "Filter" - }, - "[] | undefined; sort?: ", - { - "pluginId": "data", - "scope": "common", - "docId": "kibDataSearchPluginApi", - "section": "def-common.EsQuerySortValue", - "text": "EsQuerySortValue" - }, - "[] | undefined; highlight?: ", - { - "pluginId": "@kbn/utility-types", - "scope": "common", - "docId": "kibKbnUtilityTypesPluginApi", - "section": "def-common.SerializableRecord", - "text": "SerializableRecord" - }, - " | undefined; highlightAll?: boolean | undefined; trackTotalHits?: number | boolean | undefined; aggs?: { type: string; enabled?: boolean | undefined; id?: string | undefined; params?: {} | ", - { - "pluginId": "@kbn/utility-types", - "scope": "common", - "docId": "kibKbnUtilityTypesPluginApi", - "section": "def-common.SerializableRecord", - "text": "SerializableRecord" - }, - " | undefined; schema?: string | undefined; }[] | undefined; from?: number | undefined; size?: number | undefined; source?: boolean | ", - "Fields", - " | undefined; version?: boolean | undefined; fields?: ", - { - "pluginId": "data", - "scope": "common", - "docId": "kibDataSearchPluginApi", - "section": "def-common.SearchFieldValue", - "text": "SearchFieldValue" - }, - "[] | undefined; fieldsFromSource?: ", - "Fields", - " | undefined; index?: string | ", - { - "pluginId": "dataViews", - "scope": "common", - "docId": "kibDataViewsPluginApi", - "section": "def-common.DataViewSpec", - "text": "DataViewSpec" - }, - " | undefined; searchAfter?: ", - "SortResults", - " | undefined; timeout?: string | undefined; terminate_after?: number | undefined; parent?: ", - { - "pluginId": "data", - "scope": "common", - "docId": "kibDataSearchPluginApi", - "section": "def-common.SerializedSearchSourceFields", - "text": "SerializedSearchSourceFields" - }, - " | undefined; }" - ], - "path": "packages/kbn-generate-csv-types/index.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "@kbn/generate-csv-types", - "id": "def-common.JobParams.columns", - "type": "Array", - "tags": [], - "label": "columns", - "description": [], - "signature": [ - "string[] | undefined" - ], - "path": "packages/kbn-generate-csv-types/index.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "@kbn/generate-csv-types", - "id": "def-common.JobParams.browserTimezone", - "type": "string", - "tags": [], - "label": "browserTimezone", - "description": [], - "signature": [ - "string | undefined" - ], - "path": "packages/kbn-generate-csv-types/index.ts", - "deprecated": false, - "trackAdoption": false - } - ], - "initialIsOpen": false - } - ], - "enums": [], - "misc": [], - "objects": [] - } -} \ No newline at end of file diff --git a/api_docs/kbn_guided_onboarding.mdx b/api_docs/kbn_guided_onboarding.mdx index aabfa0eea9aae..f67f4d9cfb89e 100644 --- a/api_docs/kbn_guided_onboarding.mdx +++ b/api_docs/kbn_guided_onboarding.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-guided-onboarding title: "@kbn/guided-onboarding" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/guided-onboarding plugin -date: 2023-11-14 +date: 2023-11-16 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 a592b63f2dfca..68b6bf281411a 100644 --- a/api_docs/kbn_handlebars.mdx +++ b/api_docs/kbn_handlebars.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-handlebars title: "@kbn/handlebars" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/handlebars plugin -date: 2023-11-14 +date: 2023-11-16 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 e9cfdc18b47f1..3e1243046ba4e 100644 --- a/api_docs/kbn_hapi_mocks.mdx +++ b/api_docs/kbn_hapi_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-hapi-mocks title: "@kbn/hapi-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/hapi-mocks plugin -date: 2023-11-14 +date: 2023-11-16 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 fbf0e53016eba..9d521afacf7dd 100644 --- a/api_docs/kbn_health_gateway_server.mdx +++ b/api_docs/kbn_health_gateway_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-health-gateway-server title: "@kbn/health-gateway-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/health-gateway-server plugin -date: 2023-11-14 +date: 2023-11-16 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 ddcec01737ca2..481cb6766e777 100644 --- a/api_docs/kbn_home_sample_data_card.mdx +++ b/api_docs/kbn_home_sample_data_card.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-home-sample-data-card title: "@kbn/home-sample-data-card" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/home-sample-data-card plugin -date: 2023-11-14 +date: 2023-11-16 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 cea1cd8225f88..62b7c2f31e44c 100644 --- a/api_docs/kbn_home_sample_data_tab.mdx +++ b/api_docs/kbn_home_sample_data_tab.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-home-sample-data-tab title: "@kbn/home-sample-data-tab" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/home-sample-data-tab plugin -date: 2023-11-14 +date: 2023-11-16 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 b7a2cd2e01bf8..eff401f76683f 100644 --- a/api_docs/kbn_i18n.mdx +++ b/api_docs/kbn_i18n.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-i18n title: "@kbn/i18n" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/i18n plugin -date: 2023-11-14 +date: 2023-11-16 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 b1fcbd7d0b17d..4822e06ba5a90 100644 --- a/api_docs/kbn_i18n_react.mdx +++ b/api_docs/kbn_i18n_react.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-i18n-react title: "@kbn/i18n-react" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/i18n-react plugin -date: 2023-11-14 +date: 2023-11-16 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 4f94cd2bd1b21..173a7796634d7 100644 --- a/api_docs/kbn_import_resolver.mdx +++ b/api_docs/kbn_import_resolver.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-import-resolver title: "@kbn/import-resolver" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/import-resolver plugin -date: 2023-11-14 +date: 2023-11-16 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/import-resolver'] --- import kbnImportResolverObj from './kbn_import_resolver.devdocs.json'; diff --git a/api_docs/kbn_infra_forge.mdx b/api_docs/kbn_infra_forge.mdx index 1dade9639b9e2..9ca66fdfeeadb 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: 2023-11-14 +date: 2023-11-16 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 bd9952bd43d82..e94ffcf8e7796 100644 --- a/api_docs/kbn_interpreter.mdx +++ b/api_docs/kbn_interpreter.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-interpreter title: "@kbn/interpreter" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/interpreter plugin -date: 2023-11-14 +date: 2023-11-16 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 2ff2a51ed370c..4255f14ce2116 100644 --- a/api_docs/kbn_io_ts_utils.mdx +++ b/api_docs/kbn_io_ts_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-io-ts-utils title: "@kbn/io-ts-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/io-ts-utils plugin -date: 2023-11-14 +date: 2023-11-16 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/io-ts-utils'] --- import kbnIoTsUtilsObj from './kbn_io_ts_utils.devdocs.json'; diff --git a/api_docs/kbn_jest_serializers.mdx b/api_docs/kbn_jest_serializers.mdx index 77fcdbae5d76d..f058d33c6cfe1 100644 --- a/api_docs/kbn_jest_serializers.mdx +++ b/api_docs/kbn_jest_serializers.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-jest-serializers title: "@kbn/jest-serializers" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/jest-serializers plugin -date: 2023-11-14 +date: 2023-11-16 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 8541732d3d801..98094849fd802 100644 --- a/api_docs/kbn_journeys.mdx +++ b/api_docs/kbn_journeys.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-journeys title: "@kbn/journeys" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/journeys plugin -date: 2023-11-14 +date: 2023-11-16 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 d87c130d96c69..656670cab4d47 100644 --- a/api_docs/kbn_json_ast.mdx +++ b/api_docs/kbn_json_ast.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-json-ast title: "@kbn/json-ast" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/json-ast plugin -date: 2023-11-14 +date: 2023-11-16 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 12ed2d4b8bf76..c2a9ffbf09976 100644 --- a/api_docs/kbn_kibana_manifest_schema.mdx +++ b/api_docs/kbn_kibana_manifest_schema.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-kibana-manifest-schema title: "@kbn/kibana-manifest-schema" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/kibana-manifest-schema plugin -date: 2023-11-14 +date: 2023-11-16 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 d41eb76ffaaf7..e05ea9131bfdf 100644 --- a/api_docs/kbn_language_documentation_popover.mdx +++ b/api_docs/kbn_language_documentation_popover.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-language-documentation-popover title: "@kbn/language-documentation-popover" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/language-documentation-popover plugin -date: 2023-11-14 +date: 2023-11-16 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 8d46af2f3b191..aa1233ffc36b6 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: 2023-11-14 +date: 2023-11-16 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/lens-embeddable-utils'] --- import kbnLensEmbeddableUtilsObj from './kbn_lens_embeddable_utils.devdocs.json'; diff --git a/api_docs/kbn_logging.mdx b/api_docs/kbn_logging.mdx index 766c36a1754f4..bb27e52d7b244 100644 --- a/api_docs/kbn_logging.mdx +++ b/api_docs/kbn_logging.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-logging title: "@kbn/logging" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/logging plugin -date: 2023-11-14 +date: 2023-11-16 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 ae9a1a704564b..f0706e42dd29c 100644 --- a/api_docs/kbn_logging_mocks.mdx +++ b/api_docs/kbn_logging_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-logging-mocks title: "@kbn/logging-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/logging-mocks plugin -date: 2023-11-14 +date: 2023-11-16 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/logging-mocks'] --- import kbnLoggingMocksObj from './kbn_logging_mocks.devdocs.json'; diff --git a/api_docs/kbn_managed_vscode_config.mdx b/api_docs/kbn_managed_vscode_config.mdx index 7dab94fa765ce..8cbb1448f6f94 100644 --- a/api_docs/kbn_managed_vscode_config.mdx +++ b/api_docs/kbn_managed_vscode_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-managed-vscode-config title: "@kbn/managed-vscode-config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/managed-vscode-config plugin -date: 2023-11-14 +date: 2023-11-16 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 6039c462d7363..f509a205739f7 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: 2023-11-14 +date: 2023-11-16 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 ef5f0c111ae05..dff4e250a6658 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: 2023-11-14 +date: 2023-11-16 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 bd97bdd20e719..0300ff570e0d9 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: 2023-11-14 +date: 2023-11-16 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 3da9fc2ba1528..996684cf890a8 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: 2023-11-14 +date: 2023-11-16 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 e37c0d9d7debf..b7d9c63d46c7e 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: 2023-11-14 +date: 2023-11-16 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 83299c26b287d..7b6d4111710ba 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: 2023-11-14 +date: 2023-11-16 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 7ded057514284..cd4c29c89a5e1 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: 2023-11-14 +date: 2023-11-16 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 9f3345c8eff87..3c40ac2affa6f 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: 2023-11-14 +date: 2023-11-16 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 2a026f950fc7e..d3b0e6f85de4d 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: 2023-11-14 +date: 2023-11-16 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 eed579eb11acb..e1707d5e5c4e8 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: 2023-11-14 +date: 2023-11-16 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 e51d76e377dd3..d6c1d9205dfbc 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: 2023-11-14 +date: 2023-11-16 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 2362a22f8a9ee..88eef8bd37464 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: 2023-11-14 +date: 2023-11-16 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 c923a9582cde5..36922e6925453 100644 --- a/api_docs/kbn_mapbox_gl.mdx +++ b/api_docs/kbn_mapbox_gl.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-mapbox-gl title: "@kbn/mapbox-gl" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/mapbox-gl plugin -date: 2023-11-14 +date: 2023-11-16 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 f3d36571b0b6f..c39dc03e509a3 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: 2023-11-14 +date: 2023-11-16 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 8712b6784c093..a69c8cd6b562f 100644 --- a/api_docs/kbn_ml_agg_utils.mdx +++ b/api_docs/kbn_ml_agg_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-agg-utils title: "@kbn/ml-agg-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-agg-utils plugin -date: 2023-11-14 +date: 2023-11-16 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 5017cb992b4ac..e779cc1083991 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: 2023-11-14 +date: 2023-11-16 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_category_validator.mdx b/api_docs/kbn_ml_category_validator.mdx index ae67e6bab46b3..ed4d9fefe747d 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: 2023-11-14 +date: 2023-11-16 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 45d77397cd829..f160234bd3f7b 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: 2023-11-14 +date: 2023-11-16 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 3328e57b101f8..5a0f3fdffe950 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: 2023-11-14 +date: 2023-11-16 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 3ed357bc34046..e0ca15fc4d751 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: 2023-11-14 +date: 2023-11-16 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 91b24077b7f9b..fa09cdc394da9 100644 --- a/api_docs/kbn_ml_date_picker.mdx +++ b/api_docs/kbn_ml_date_picker.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-date-picker title: "@kbn/ml-date-picker" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-date-picker plugin -date: 2023-11-14 +date: 2023-11-16 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 3ec816f271459..cc6eb09ac8d3e 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: 2023-11-14 +date: 2023-11-16 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 faeeaff8c44ad..abb315ecc6a99 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: 2023-11-14 +date: 2023-11-16 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 9eeab8ce27b9c..16e23cfc25c48 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: 2023-11-14 +date: 2023-11-16 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 ea57d25ee80d3..9bd7dd87854a7 100644 --- a/api_docs/kbn_ml_is_defined.mdx +++ b/api_docs/kbn_ml_is_defined.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-is-defined title: "@kbn/ml-is-defined" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-is-defined plugin -date: 2023-11-14 +date: 2023-11-16 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 2c44703af906e..8d467f203c2bf 100644 --- a/api_docs/kbn_ml_is_populated_object.mdx +++ b/api_docs/kbn_ml_is_populated_object.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-is-populated-object title: "@kbn/ml-is-populated-object" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-is-populated-object plugin -date: 2023-11-14 +date: 2023-11-16 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 7326a74d79a76..0f87482f4ae3d 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: 2023-11-14 +date: 2023-11-16 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 1132cd5bb7fa0..c22ed444a3846 100644 --- a/api_docs/kbn_ml_local_storage.mdx +++ b/api_docs/kbn_ml_local_storage.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-local-storage title: "@kbn/ml-local-storage" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-local-storage plugin -date: 2023-11-14 +date: 2023-11-16 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 25acc8ca774a6..0b2a5c31fae69 100644 --- a/api_docs/kbn_ml_nested_property.mdx +++ b/api_docs/kbn_ml_nested_property.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-nested-property title: "@kbn/ml-nested-property" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-nested-property plugin -date: 2023-11-14 +date: 2023-11-16 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 d980fea036b32..0867d6b273f7a 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: 2023-11-14 +date: 2023-11-16 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 ca73f435c18a1..de86a37513a8c 100644 --- a/api_docs/kbn_ml_query_utils.mdx +++ b/api_docs/kbn_ml_query_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-query-utils title: "@kbn/ml-query-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-query-utils plugin -date: 2023-11-14 +date: 2023-11-16 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 522448d33b1d9..2aea55e5a1e64 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: 2023-11-14 +date: 2023-11-16 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 4e7a592d60c5a..0b2babc59f207 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: 2023-11-14 +date: 2023-11-16 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 5137fa5e67ad7..1a286951d5864 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: 2023-11-14 +date: 2023-11-16 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 22618e760b6ee..0459040752e4d 100644 --- a/api_docs/kbn_ml_string_hash.mdx +++ b/api_docs/kbn_ml_string_hash.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-string-hash title: "@kbn/ml-string-hash" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-string-hash plugin -date: 2023-11-14 +date: 2023-11-16 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_trained_models_utils.mdx b/api_docs/kbn_ml_trained_models_utils.mdx index 4f030b42b7761..0a09588940bd3 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: 2023-11-14 +date: 2023-11-16 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_url_state.mdx b/api_docs/kbn_ml_url_state.mdx index 2f5aada8156fa..17b5193dbc83e 100644 --- a/api_docs/kbn_ml_url_state.mdx +++ b/api_docs/kbn_ml_url_state.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-url-state title: "@kbn/ml-url-state" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-url-state plugin -date: 2023-11-14 +date: 2023-11-16 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-url-state'] --- import kbnMlUrlStateObj from './kbn_ml_url_state.devdocs.json'; diff --git a/api_docs/kbn_monaco.devdocs.json b/api_docs/kbn_monaco.devdocs.json index c7d87a27c0872..f15a94ffd5541 100644 --- a/api_docs/kbn_monaco.devdocs.json +++ b/api_docs/kbn_monaco.devdocs.json @@ -630,7 +630,7 @@ "label": "kind", "description": [], "signature": [ - "\"type\" | \"keyword\" | \"property\" | \"field\" | \"method\" | \"class\" | \"constructor\"" + "\"type\" | \"keyword\" | \"property\" | \"field\" | \"class\" | \"method\" | \"constructor\"" ], "path": "packages/kbn-monaco/src/painless/types.ts", "deprecated": false, @@ -798,7 +798,7 @@ "label": "PainlessCompletionKind", "description": [], "signature": [ - "\"type\" | \"keyword\" | \"property\" | \"field\" | \"method\" | \"class\" | \"constructor\"" + "\"type\" | \"keyword\" | \"property\" | \"field\" | \"class\" | \"method\" | \"constructor\"" ], "path": "packages/kbn-monaco/src/painless/types.ts", "deprecated": false, diff --git a/api_docs/kbn_monaco.mdx b/api_docs/kbn_monaco.mdx index 74b97e2c9c7f2..f8ef704a8ff1f 100644 --- a/api_docs/kbn_monaco.mdx +++ b/api_docs/kbn_monaco.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-monaco title: "@kbn/monaco" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/monaco plugin -date: 2023-11-14 +date: 2023-11-16 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 386f2d52e2920..56e5bbb6482f8 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: 2023-11-14 +date: 2023-11-16 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 e7d186cde4fc0..ccda394924ffc 100644 --- a/api_docs/kbn_observability_alert_details.mdx +++ b/api_docs/kbn_observability_alert_details.mdx @@ -8,14 +8,14 @@ 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: 2023-11-14 +date: 2023-11-16 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/observability-alert-details'] --- import kbnObservabilityAlertDetailsObj from './kbn_observability_alert_details.devdocs.json'; -Contact [@elastic/actionable-observability](https://github.com/orgs/elastic/teams/actionable-observability) for questions regarding this plugin. +Contact [@elastic/obs-ux-management-team](https://github.com/orgs/elastic/teams/obs-ux-management-team) for questions regarding this plugin. **Code health stats** diff --git a/api_docs/kbn_observability_alerting_test_data.devdocs.json b/api_docs/kbn_observability_alerting_test_data.devdocs.json index 71f9df827784d..96da803aa4b60 100644 --- a/api_docs/kbn_observability_alerting_test_data.devdocs.json +++ b/api_docs/kbn_observability_alerting_test_data.devdocs.json @@ -434,9 +434,7 @@ "label": "criteria", "description": [], "signature": [ - "{ aggType: ", - "Aggregators", - "; comparator: ", + "{ aggType: string; comparator: ", "Comparator", "; threshold: number[]; timeSize: number; timeUnit: string; metrics: { name: string; filter: string; aggType: ", "Aggregators", @@ -599,9 +597,7 @@ "label": "criteria", "description": [], "signature": [ - "{ aggType: ", - "Aggregators", - "; comparator: ", + "{ aggType: string; comparator: ", "Comparator", "; threshold: number[]; timeSize: number; timeUnit: string; metrics: { name: string; filter: string; aggType: ", "Aggregators", @@ -778,9 +774,7 @@ "label": "criteria", "description": [], "signature": [ - "{ aggType: ", - "Aggregators", - "; comparator: ", + "{ aggType: string; comparator: ", "Comparator", "; threshold: number[]; timeSize: number; timeUnit: string; metrics: { name: string; filter: string; aggType: ", "Aggregators", @@ -943,9 +937,7 @@ "label": "criteria", "description": [], "signature": [ - "{ aggType: ", - "Aggregators", - "; comparator: ", + "{ aggType: string; comparator: ", "Comparator", "; threshold: number[]; timeSize: number; timeUnit: string; metrics: { name: string; field: string; aggType: ", "Aggregators", @@ -1108,9 +1100,7 @@ "label": "criteria", "description": [], "signature": [ - "{ aggType: ", - "Aggregators", - "; comparator: ", + "{ aggType: string; comparator: ", "Comparator", "; threshold: number[]; timeSize: number; timeUnit: string; metrics: { name: string; field: string; aggType: ", "Aggregators", @@ -1287,9 +1277,7 @@ "label": "criteria", "description": [], "signature": [ - "{ aggType: ", - "Aggregators", - "; comparator: ", + "{ aggType: string; comparator: ", "Comparator", "; threshold: number[]; timeSize: number; timeUnit: string; metrics: { name: string; field: string; aggType: ", "Aggregators", diff --git a/api_docs/kbn_observability_alerting_test_data.mdx b/api_docs/kbn_observability_alerting_test_data.mdx index 729d413783a9b..596f990e31fa8 100644 --- a/api_docs/kbn_observability_alerting_test_data.mdx +++ b/api_docs/kbn_observability_alerting_test_data.mdx @@ -8,14 +8,14 @@ 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: 2023-11-14 +date: 2023-11-16 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/observability-alerting-test-data'] --- import kbnObservabilityAlertingTestDataObj from './kbn_observability_alerting_test_data.devdocs.json'; -Contact [@elastic/actionable-observability](https://github.com/orgs/elastic/teams/actionable-observability) for questions regarding this plugin. +Contact [@elastic/obs-ux-management-team](https://github.com/orgs/elastic/teams/obs-ux-management-team) for questions regarding this plugin. **Code health stats** diff --git a/api_docs/kbn_openapi_generator.mdx b/api_docs/kbn_openapi_generator.mdx index fd061015ae64b..a38da4be53048 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: 2023-11-14 +date: 2023-11-16 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 11542a7605782..9f6322c9f087b 100644 --- a/api_docs/kbn_optimizer.mdx +++ b/api_docs/kbn_optimizer.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-optimizer title: "@kbn/optimizer" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/optimizer plugin -date: 2023-11-14 +date: 2023-11-16 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 a37adc689ba33..7763f9b79e4ee 100644 --- a/api_docs/kbn_optimizer_webpack_helpers.mdx +++ b/api_docs/kbn_optimizer_webpack_helpers.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-optimizer-webpack-helpers title: "@kbn/optimizer-webpack-helpers" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/optimizer-webpack-helpers plugin -date: 2023-11-14 +date: 2023-11-16 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.devdocs.json b/api_docs/kbn_osquery_io_ts_types.devdocs.json index 65501b5031659..4fd8870da6eaf 100644 --- a/api_docs/kbn_osquery_io_ts_types.devdocs.json +++ b/api_docs/kbn_osquery_io_ts_types.devdocs.json @@ -457,6 +457,36 @@ "trackAdoption": false, "initialIsOpen": false }, + { + "parentPluginId": "@kbn/osquery-io-ts-types", + "id": "def-common.Timeout", + "type": "Type", + "tags": [], + "label": "Timeout", + "description": [], + "signature": [ + "number" + ], + "path": "packages/kbn-osquery-io-ts-types/src/live_query/index.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/osquery-io-ts-types", + "id": "def-common.TimeoutOrUndefined", + "type": "Type", + "tags": [], + "label": "TimeoutOrUndefined", + "description": [], + "signature": [ + "number | undefined" + ], + "path": "packages/kbn-osquery-io-ts-types/src/live_query/index.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, { "parentPluginId": "@kbn/osquery-io-ts-types", "id": "def-common.Version", @@ -1352,6 +1382,42 @@ "trackAdoption": false, "initialIsOpen": false }, + { + "parentPluginId": "@kbn/osquery-io-ts-types", + "id": "def-common.timeout", + "type": "Object", + "tags": [], + "label": "timeout", + "description": [], + "signature": [ + "Type", + "" + ], + "path": "packages/kbn-osquery-io-ts-types/src/live_query/index.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/osquery-io-ts-types", + "id": "def-common.timeoutOrUndefined", + "type": "Object", + "tags": [], + "label": "timeoutOrUndefined", + "description": [], + "signature": [ + "UnionC", + "<[", + "Type", + ", ", + "UndefinedC", + "]>" + ], + "path": "packages/kbn-osquery-io-ts-types/src/live_query/index.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, { "parentPluginId": "@kbn/osquery-io-ts-types", "id": "def-common.version", diff --git a/api_docs/kbn_osquery_io_ts_types.mdx b/api_docs/kbn_osquery_io_ts_types.mdx index 2644a5e5ca3fa..df617bbac03d2 100644 --- a/api_docs/kbn_osquery_io_ts_types.mdx +++ b/api_docs/kbn_osquery_io_ts_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-osquery-io-ts-types title: "@kbn/osquery-io-ts-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/osquery-io-ts-types plugin -date: 2023-11-14 +date: 2023-11-16 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/osquery-io-ts-types'] --- import kbnOsqueryIoTsTypesObj from './kbn_osquery_io_ts_types.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/security-asset-management](https://github.com/orgs/elastic/tea | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 62 | 0 | 62 | 0 | +| 66 | 0 | 66 | 0 | ## Common diff --git a/api_docs/kbn_performance_testing_dataset_extractor.mdx b/api_docs/kbn_performance_testing_dataset_extractor.mdx index f9af1703da81f..4556ae39a65e4 100644 --- a/api_docs/kbn_performance_testing_dataset_extractor.mdx +++ b/api_docs/kbn_performance_testing_dataset_extractor.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-performance-testing-dataset-extractor title: "@kbn/performance-testing-dataset-extractor" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/performance-testing-dataset-extractor plugin -date: 2023-11-14 +date: 2023-11-16 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/performance-testing-dataset-extractor'] --- import kbnPerformanceTestingDatasetExtractorObj from './kbn_performance_testing_dataset_extractor.devdocs.json'; diff --git a/api_docs/kbn_plugin_generator.mdx b/api_docs/kbn_plugin_generator.mdx index 5aac9009580f0..14421a7c80627 100644 --- a/api_docs/kbn_plugin_generator.mdx +++ b/api_docs/kbn_plugin_generator.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-plugin-generator title: "@kbn/plugin-generator" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/plugin-generator plugin -date: 2023-11-14 +date: 2023-11-16 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 9394ec6f056d6..ec8306b1fd837 100644 --- a/api_docs/kbn_plugin_helpers.mdx +++ b/api_docs/kbn_plugin_helpers.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-plugin-helpers title: "@kbn/plugin-helpers" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/plugin-helpers plugin -date: 2023-11-14 +date: 2023-11-16 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/plugin-helpers'] --- import kbnPluginHelpersObj from './kbn_plugin_helpers.devdocs.json'; diff --git a/api_docs/kbn_profiling_utils.mdx b/api_docs/kbn_profiling_utils.mdx index 69c793b1f336c..86badc0e585ec 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: 2023-11-14 +date: 2023-11-16 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 5b91f251f9030..67a8c86aaf8b1 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: 2023-11-14 +date: 2023-11-16 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 7f134dd46c807..2575b407c76e2 100644 --- a/api_docs/kbn_react_field.mdx +++ b/api_docs/kbn_react_field.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-react-field title: "@kbn/react-field" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/react-field plugin -date: 2023-11-14 +date: 2023-11-16 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/react-field'] --- import kbnReactFieldObj from './kbn_react_field.devdocs.json'; diff --git a/api_docs/kbn_react_kibana_context_common.mdx b/api_docs/kbn_react_kibana_context_common.mdx index 723ba0d506f12..b0afe199e9ad2 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: 2023-11-14 +date: 2023-11-16 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 e6230b0de3a65..36e77747123b6 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: 2023-11-14 +date: 2023-11-16 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 ddcff99da6020..a87316950a556 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: 2023-11-14 +date: 2023-11-16 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 711617ff8f70c..172ff21e7a517 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: 2023-11-14 +date: 2023-11-16 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 423a11ad1382f..b0eb24de31908 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: 2023-11-14 +date: 2023-11-16 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 9deeea7b2d350..b72b1e56e37a1 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: 2023-11-14 +date: 2023-11-16 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 e98676fbad127..dc8ae220028e1 100644 --- a/api_docs/kbn_repo_file_maps.mdx +++ b/api_docs/kbn_repo_file_maps.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-repo-file-maps title: "@kbn/repo-file-maps" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/repo-file-maps plugin -date: 2023-11-14 +date: 2023-11-16 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 f8ee4c0579b41..b70dc4ee827a9 100644 --- a/api_docs/kbn_repo_linter.mdx +++ b/api_docs/kbn_repo_linter.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-repo-linter title: "@kbn/repo-linter" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/repo-linter plugin -date: 2023-11-14 +date: 2023-11-16 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 3ae139932e745..bc0a310b96c7f 100644 --- a/api_docs/kbn_repo_path.mdx +++ b/api_docs/kbn_repo_path.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-repo-path title: "@kbn/repo-path" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/repo-path plugin -date: 2023-11-14 +date: 2023-11-16 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 7090363cc6398..04502f0b603d5 100644 --- a/api_docs/kbn_repo_source_classifier.mdx +++ b/api_docs/kbn_repo_source_classifier.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-repo-source-classifier title: "@kbn/repo-source-classifier" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/repo-source-classifier plugin -date: 2023-11-14 +date: 2023-11-16 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.devdocs.json b/api_docs/kbn_reporting_common.devdocs.json index bb90486c2546c..68cf96719cd61 100644 --- a/api_docs/kbn_reporting_common.devdocs.json +++ b/api_docs/kbn_reporting_common.devdocs.json @@ -892,6 +892,39 @@ } ], "functions": [ + { + "parentPluginId": "@kbn/reporting-common", + "id": "def-common.buildKibanaPath", + "type": "Function", + "tags": [], + "label": "buildKibanaPath", + "description": [], + "signature": [ + "({ basePath, appPath, spaceId }: Args) => string" + ], + "path": "packages/kbn-reporting/common/build_kibana_path.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/reporting-common", + "id": "def-common.buildKibanaPath.$1", + "type": "Object", + "tags": [], + "label": "{ basePath, appPath, spaceId }", + "description": [], + "signature": [ + "Args" + ], + "path": "packages/kbn-reporting/common/build_kibana_path.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [], + "initialIsOpen": false + }, { "parentPluginId": "@kbn/reporting-common", "id": "def-common.byteSizeValueToNumber", @@ -973,6 +1006,25 @@ "returnComment": [], "initialIsOpen": false }, + { + "parentPluginId": "@kbn/reporting-common", + "id": "def-common.getRedirectAppPath", + "type": "Function", + "tags": [], + "label": "getRedirectAppPath", + "description": [ + "\nA way to get the client side route for the reporting redirect app.\n\nTODO: Add a job ID and a locator to use so that we can redirect without expecting state to\nbe injected to the page" + ], + "signature": [ + "() => string" + ], + "path": "packages/kbn-reporting/common/constants.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [], + "initialIsOpen": false + }, { "parentPluginId": "@kbn/reporting-common", "id": "def-common.numberToDuration", @@ -1008,31 +1060,6 @@ } ], "interfaces": [ - { - "parentPluginId": "@kbn/reporting-common", - "id": "def-common.CsvMetrics", - "type": "Interface", - "tags": [], - "label": "CsvMetrics", - "description": [], - "path": "packages/kbn-reporting/common/metrics.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "@kbn/reporting-common", - "id": "def-common.CsvMetrics.rows", - "type": "number", - "tags": [], - "label": "rows", - "description": [], - "path": "packages/kbn-reporting/common/metrics.ts", - "deprecated": false, - "trackAdoption": false - } - ], - "initialIsOpen": false - }, { "parentPluginId": "@kbn/reporting-common", "id": "def-common.ReportingError", @@ -1064,191 +1091,257 @@ } ], "initialIsOpen": false + } + ], + "enums": [ + { + "parentPluginId": "@kbn/reporting-common", + "id": "def-common.JOB_STATUS", + "type": "Enum", + "tags": [], + "label": "JOB_STATUS", + "description": [], + "path": "packages/kbn-reporting/common/constants.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + } + ], + "misc": [ + { + "parentPluginId": "@kbn/reporting-common", + "id": "def-common.ALLOWED_JOB_CONTENT_TYPES", + "type": "Array", + "tags": [], + "label": "ALLOWED_JOB_CONTENT_TYPES", + "description": [], + "signature": [ + "string[]" + ], + "path": "packages/kbn-reporting/common/constants.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false }, { "parentPluginId": "@kbn/reporting-common", - "id": "def-common.TaskRunMetrics", - "type": "Interface", + "id": "def-common.API_USAGE_COUNTER_TYPE", + "type": "string", "tags": [], - "label": "TaskRunMetrics", + "label": "API_USAGE_COUNTER_TYPE", "description": [], - "path": "packages/kbn-reporting/common/metrics.ts", + "signature": [ + "\"reportingApi\"" + ], + "path": "packages/kbn-reporting/common/constants.ts", "deprecated": false, "trackAdoption": false, - "children": [ - { - "parentPluginId": "@kbn/reporting-common", - "id": "def-common.TaskRunMetrics.csv", - "type": "Object", - "tags": [], - "label": "csv", - "description": [], - "signature": [ - { - "pluginId": "@kbn/reporting-common", - "scope": "common", - "docId": "kibKbnReportingCommonPluginApi", - "section": "def-common.CsvMetrics", - "text": "CsvMetrics" - }, - " | undefined" - ], - "path": "packages/kbn-reporting/common/metrics.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "@kbn/reporting-common", - "id": "def-common.TaskRunMetrics.png", - "type": "Object", - "tags": [], - "label": "png", - "description": [], - "signature": [ - "PerformanceMetrics", - " | undefined" - ], - "path": "packages/kbn-reporting/common/metrics.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "@kbn/reporting-common", - "id": "def-common.TaskRunMetrics.pdf", - "type": "Object", - "tags": [], - "label": "pdf", - "description": [], - "signature": [ - "PdfScreenshotMetrics", - " | undefined" - ], - "path": "packages/kbn-reporting/common/metrics.ts", - "deprecated": false, - "trackAdoption": false - } + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/reporting-common", + "id": "def-common.API_USAGE_ERROR_TYPE", + "type": "string", + "tags": [], + "label": "API_USAGE_ERROR_TYPE", + "description": [], + "signature": [ + "\"reportingApiError\"" ], + "path": "packages/kbn-reporting/common/constants.ts", + "deprecated": false, + "trackAdoption": false, "initialIsOpen": false }, { "parentPluginId": "@kbn/reporting-common", - "id": "def-common.TaskRunResult", - "type": "Interface", + "id": "def-common.ILM_POLICY_NAME", + "type": "string", "tags": [], - "label": "TaskRunResult", + "label": "ILM_POLICY_NAME", "description": [], - "path": "packages/kbn-reporting/common/metrics.ts", + "signature": [ + "\"kibana-reporting\"" + ], + "path": "packages/kbn-reporting/common/constants.ts", "deprecated": false, "trackAdoption": false, - "children": [ - { - "parentPluginId": "@kbn/reporting-common", - "id": "def-common.TaskRunResult.content_type", - "type": "CompoundType", - "tags": [], - "label": "content_type", - "description": [], - "signature": [ - "string | null" - ], - "path": "packages/kbn-reporting/common/metrics.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "@kbn/reporting-common", - "id": "def-common.TaskRunResult.csv_contains_formulas", - "type": "CompoundType", - "tags": [], - "label": "csv_contains_formulas", - "description": [], - "signature": [ - "boolean | undefined" - ], - "path": "packages/kbn-reporting/common/metrics.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "@kbn/reporting-common", - "id": "def-common.TaskRunResult.max_size_reached", - "type": "CompoundType", - "tags": [], - "label": "max_size_reached", - "description": [], - "signature": [ - "boolean | undefined" - ], - "path": "packages/kbn-reporting/common/metrics.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "@kbn/reporting-common", - "id": "def-common.TaskRunResult.warnings", - "type": "Array", - "tags": [], - "label": "warnings", - "description": [], - "signature": [ - "string[] | undefined" - ], - "path": "packages/kbn-reporting/common/metrics.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "@kbn/reporting-common", - "id": "def-common.TaskRunResult.metrics", - "type": "Object", - "tags": [], - "label": "metrics", - "description": [], - "signature": [ - { - "pluginId": "@kbn/reporting-common", - "scope": "common", - "docId": "kibKbnReportingCommonPluginApi", - "section": "def-common.TaskRunMetrics", - "text": "TaskRunMetrics" - }, - " | undefined" - ], - "path": "packages/kbn-reporting/common/metrics.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "@kbn/reporting-common", - "id": "def-common.TaskRunResult.error_code", - "type": "string", - "tags": [], - "label": "error_code", - "description": [ - "\nWhen running a report task we may finish with warnings that were triggered\nby an error. We can pass the error code via the task run result to the\ntask runner so that it can be recorded for telemetry.\n\nAlternatively, this field can be populated in the event that the task does\nnot complete in the task runner's error handler." - ], - "signature": [ - "string | undefined" - ], - "path": "packages/kbn-reporting/common/metrics.ts", - "deprecated": false, - "trackAdoption": false - } + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/reporting-common", + "id": "def-common.JOB_COMPLETION_NOTIFICATIONS_SESSION_KEY", + "type": "string", + "tags": [], + "label": "JOB_COMPLETION_NOTIFICATIONS_SESSION_KEY", + "description": [], + "signature": [ + "\"xpack.reporting.jobCompletionNotifications\"" ], + "path": "packages/kbn-reporting/common/constants.ts", + "deprecated": false, + "trackAdoption": false, "initialIsOpen": false - } - ], - "enums": [], - "misc": [ + }, + { + "parentPluginId": "@kbn/reporting-common", + "id": "def-common.LICENSE_TYPE_BASIC", + "type": "string", + "tags": [], + "label": "LICENSE_TYPE_BASIC", + "description": [], + "signature": [ + "\"basic\"" + ], + "path": "packages/kbn-reporting/common/constants.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/reporting-common", + "id": "def-common.LICENSE_TYPE_CLOUD_STANDARD", + "type": "string", + "tags": [], + "label": "LICENSE_TYPE_CLOUD_STANDARD", + "description": [], + "signature": [ + "\"standard\"" + ], + "path": "packages/kbn-reporting/common/constants.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/reporting-common", + "id": "def-common.LICENSE_TYPE_ENTERPRISE", + "type": "string", + "tags": [], + "label": "LICENSE_TYPE_ENTERPRISE", + "description": [], + "signature": [ + "\"enterprise\"" + ], + "path": "packages/kbn-reporting/common/constants.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/reporting-common", + "id": "def-common.LICENSE_TYPE_GOLD", + "type": "string", + "tags": [], + "label": "LICENSE_TYPE_GOLD", + "description": [], + "signature": [ + "\"gold\"" + ], + "path": "packages/kbn-reporting/common/constants.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/reporting-common", + "id": "def-common.LICENSE_TYPE_PLATINUM", + "type": "string", + "tags": [], + "label": "LICENSE_TYPE_PLATINUM", + "description": [], + "signature": [ + "\"platinum\"" + ], + "path": "packages/kbn-reporting/common/constants.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/reporting-common", + "id": "def-common.LICENSE_TYPE_TRIAL", + "type": "string", + "tags": [], + "label": "LICENSE_TYPE_TRIAL", + "description": [], + "signature": [ + "\"trial\"" + ], + "path": "packages/kbn-reporting/common/constants.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/reporting-common", + "id": "def-common.PLUGIN_ID", + "type": "string", + "tags": [], + "label": "PLUGIN_ID", + "description": [], + "signature": [ + "\"reporting\"" + ], + "path": "packages/kbn-reporting/common/constants.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/reporting-common", + "id": "def-common.REPORTING_MANAGEMENT_HOME", + "type": "string", + "tags": [], + "label": "REPORTING_MANAGEMENT_HOME", + "description": [], + "signature": [ + "\"/app/management/insightsAndAlerting/reporting\"" + ], + "path": "packages/kbn-reporting/common/constants.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/reporting-common", + "id": "def-common.REPORTING_REDIRECT_LOCATOR_STORE_KEY", + "type": "string", + "tags": [], + "label": "REPORTING_REDIRECT_LOCATOR_STORE_KEY", + "description": [], + "signature": [ + "\"__REPORTING_REDIRECT_LOCATOR_STORE_KEY__\"" + ], + "path": "packages/kbn-reporting/common/constants.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, { "parentPluginId": "@kbn/reporting-common", - "id": "def-common.CSV_REPORTING_ACTION", + "id": "def-common.REPORTING_SYSTEM_INDEX", "type": "string", "tags": [], - "label": "CSV_REPORTING_ACTION", + "label": "REPORTING_SYSTEM_INDEX", "description": [], "signature": [ - "\"downloadCsvReport\"" + "\".reporting\"" + ], + "path": "packages/kbn-reporting/common/constants.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/reporting-common", + "id": "def-common.REPORTING_TRANSACTION_TYPE", + "type": "string", + "tags": [], + "label": "REPORTING_TRANSACTION_TYPE", + "description": [], + "signature": [ + "\"reporting\"" ], "path": "packages/kbn-reporting/common/constants.ts", "deprecated": false, @@ -1299,6 +1392,21 @@ "deprecated": false, "trackAdoption": false, "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/reporting-common", + "id": "def-common.UNVERSIONED_VERSION", + "type": "string", + "tags": [], + "label": "UNVERSIONED_VERSION", + "description": [], + "signature": [ + "\"7.14.0\"" + ], + "path": "packages/kbn-reporting/common/constants.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false } ], "objects": [] diff --git a/api_docs/kbn_reporting_common.mdx b/api_docs/kbn_reporting_common.mdx index e5fac5104e305..cbabbb3542a21 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: 2023-11-14 +date: 2023-11-16 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/reporting-common'] --- import kbnReportingCommonObj from './kbn_reporting_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 | |-------------------|-----------|------------------------|-----------------| -| 73 | 0 | 65 | 0 | +| 80 | 0 | 72 | 7 | ## Common @@ -34,6 +34,9 @@ Contact [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sh ### Interfaces +### Enums + + ### Consts, variables and types diff --git a/api_docs/kbn_reporting_export_types_csv.devdocs.json b/api_docs/kbn_reporting_export_types_csv.devdocs.json new file mode 100644 index 0000000000000..60f6311b05b9c --- /dev/null +++ b/api_docs/kbn_reporting_export_types_csv.devdocs.json @@ -0,0 +1,1171 @@ +{ + "id": "@kbn/reporting-export-types-csv", + "client": { + "classes": [], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] + }, + "server": { + "classes": [ + { + "parentPluginId": "@kbn/reporting-export-types-csv", + "id": "def-server.CsvSearchSourceExportType", + "type": "Class", + "tags": [], + "label": "CsvSearchSourceExportType", + "description": [], + "signature": [ + { + "pluginId": "@kbn/reporting-export-types-csv", + "scope": "server", + "docId": "kibKbnReportingExportTypesCsvPluginApi", + "section": "def-server.CsvSearchSourceExportType", + "text": "CsvSearchSourceExportType" + }, + " extends ", + { + "pluginId": "@kbn/reporting-server", + "scope": "server", + "docId": "kibKbnReportingServerPluginApi", + "section": "def-server.ExportType", + "text": "ExportType" + }, + "<", + { + "pluginId": "@kbn/reporting-export-types-csv-common", + "scope": "common", + "docId": "kibKbnReportingExportTypesCsvCommonPluginApi", + "section": "def-common.JobParamsCSV", + "text": "JobParamsCSV" + }, + ", ", + { + "pluginId": "@kbn/reporting-export-types-csv-common", + "scope": "common", + "docId": "kibKbnReportingExportTypesCsvCommonPluginApi", + "section": "def-common.TaskPayloadCSV", + "text": "TaskPayloadCSV" + }, + ", ", + { + "pluginId": "@kbn/reporting-server", + "scope": "server", + "docId": "kibKbnReportingServerPluginApi", + "section": "def-server.BaseExportTypeSetupDeps", + "text": "BaseExportTypeSetupDeps" + }, + ", CsvSearchSourceExportTypeStartDeps>" + ], + "path": "packages/kbn-reporting/export_types/csv/csv_searchsource.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/reporting-export-types-csv", + "id": "def-server.CsvSearchSourceExportType.id", + "type": "string", + "tags": [], + "label": "id", + "description": [], + "path": "packages/kbn-reporting/export_types/csv/csv_searchsource.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/reporting-export-types-csv", + "id": "def-server.CsvSearchSourceExportType.name", + "type": "string", + "tags": [], + "label": "name", + "description": [], + "path": "packages/kbn-reporting/export_types/csv/csv_searchsource.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/reporting-export-types-csv", + "id": "def-server.CsvSearchSourceExportType.jobType", + "type": "string", + "tags": [], + "label": "jobType", + "description": [], + "path": "packages/kbn-reporting/export_types/csv/csv_searchsource.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/reporting-export-types-csv", + "id": "def-server.CsvSearchSourceExportType.jobContentEncoding", + "type": "string", + "tags": [], + "label": "jobContentEncoding", + "description": [], + "signature": [ + "\"base64\"" + ], + "path": "packages/kbn-reporting/export_types/csv/csv_searchsource.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/reporting-export-types-csv", + "id": "def-server.CsvSearchSourceExportType.jobContentExtension", + "type": "string", + "tags": [], + "label": "jobContentExtension", + "description": [], + "signature": [ + "\"csv\"" + ], + "path": "packages/kbn-reporting/export_types/csv/csv_searchsource.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/reporting-export-types-csv", + "id": "def-server.CsvSearchSourceExportType.validLicenses", + "type": "Array", + "tags": [], + "label": "validLicenses", + "description": [], + "signature": [ + "(\"basic\" | \"standard\" | \"gold\" | \"platinum\" | \"enterprise\" | \"trial\")[]" + ], + "path": "packages/kbn-reporting/export_types/csv/csv_searchsource.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/reporting-export-types-csv", + "id": "def-server.CsvSearchSourceExportType.Unnamed", + "type": "Function", + "tags": [], + "label": "Constructor", + "description": [], + "signature": [ + "any" + ], + "path": "packages/kbn-reporting/export_types/csv/csv_searchsource.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/reporting-export-types-csv", + "id": "def-server.CsvSearchSourceExportType.Unnamed.$1", + "type": "Object", + "tags": [], + "label": "args", + "description": [], + "signature": [ + "[core: ", + { + "pluginId": "@kbn/core-lifecycle-server", + "scope": "common", + "docId": "kibKbnCoreLifecycleServerPluginApi", + "section": "def-common.CoreSetup", + "text": "CoreSetup" + }, + ", config: Readonly<{ encryptionKey?: string | undefined; } & { enabled: boolean; capture: Readonly<{} & { maxAttempts: number; }>; kibanaServer: Readonly<{ hostname?: string | undefined; protocol?: string | undefined; port?: number | undefined; } & {}>; queue: Readonly<{} & { timeout: number | moment.Duration; pollInterval: number | moment.Duration; indexInterval: string; pollEnabled: boolean; pollIntervalErrorMultiplier: number; }>; csv: Readonly<{} & { scroll: Readonly<{} & { duration: string; size: number; }>; checkForFormulas: boolean; escapeFormulaValues: boolean; enablePanelActionDownload: boolean; maxSizeBytes: number | ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ByteSizeValue", + "text": "ByteSizeValue" + }, + "; useByteOrderMarkEncoding: boolean; }>; roles: Readonly<{} & { enabled: boolean; allow: string[]; }>; poll: Readonly<{} & { jobCompletionNotifier: Readonly<{} & { interval: number; intervalErrorMultiplier: number; }>; jobsRefresh: Readonly<{} & { interval: number; intervalErrorMultiplier: number; }>; }>; export_types: Readonly<{} & { csv: Readonly<{} & { enabled: boolean; }>; png: Readonly<{} & { enabled: boolean; }>; pdf: Readonly<{} & { enabled: boolean; }>; }>; statefulSettings: Readonly<{} & { enabled: boolean; }>; }>, logger: ", + { + "pluginId": "@kbn/logging", + "scope": "common", + "docId": "kibKbnLoggingPluginApi", + "section": "def-common.Logger", + "text": "Logger" + }, + ", context: ", + { + "pluginId": "@kbn/core-plugins-server", + "scope": "common", + "docId": "kibKbnCorePluginsServerPluginApi", + "section": "def-common.PluginInitializerContext", + "text": "PluginInitializerContext" + }, + "; kibanaServer: Readonly<{ hostname?: string | undefined; protocol?: string | undefined; port?: number | undefined; } & {}>; queue: Readonly<{} & { timeout: number | moment.Duration; pollInterval: number | moment.Duration; indexInterval: string; pollEnabled: boolean; pollIntervalErrorMultiplier: number; }>; csv: Readonly<{} & { scroll: Readonly<{} & { duration: string; size: number; }>; checkForFormulas: boolean; escapeFormulaValues: boolean; enablePanelActionDownload: boolean; maxSizeBytes: number | ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ByteSizeValue", + "text": "ByteSizeValue" + }, + "; useByteOrderMarkEncoding: boolean; }>; roles: Readonly<{} & { enabled: boolean; allow: string[]; }>; poll: Readonly<{} & { jobCompletionNotifier: Readonly<{} & { interval: number; intervalErrorMultiplier: number; }>; jobsRefresh: Readonly<{} & { interval: number; intervalErrorMultiplier: number; }>; }>; export_types: Readonly<{} & { csv: Readonly<{} & { enabled: boolean; }>; png: Readonly<{} & { enabled: boolean; }>; pdf: Readonly<{} & { enabled: boolean; }>; }>; statefulSettings: Readonly<{} & { enabled: boolean; }>; }>>]" + ], + "path": "packages/kbn-reporting/export_types/csv/csv_searchsource.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/reporting-export-types-csv", + "id": "def-server.CsvSearchSourceExportType.createJob", + "type": "Function", + "tags": [], + "label": "createJob", + "description": [], + "signature": [ + "(jobParams: ", + { + "pluginId": "@kbn/reporting-export-types-csv-common", + "scope": "common", + "docId": "kibKbnReportingExportTypesCsvCommonPluginApi", + "section": "def-common.JobParamsCSV", + "text": "JobParamsCSV" + }, + ") => Promise<{ searchSource: ", + { + "pluginId": "data", + "scope": "common", + "docId": "kibDataSearchPluginApi", + "section": "def-common.SerializedSearchSourceFields", + "text": "SerializedSearchSourceFields" + }, + "; columns?: string[] | undefined; layout?: { id?: ", + { + "pluginId": "screenshotting", + "scope": "common", + "docId": "kibScreenshottingPluginApi", + "section": "def-common.LayoutType", + "text": "LayoutType" + }, + " | undefined; dimensions?: { width: number; height: number; } | undefined; selectors?: Partial<", + "LayoutSelectorDictionary", + "> | undefined; zoom?: number | undefined; } | undefined; objectType: string; title: string; browserTimezone: string; version: string; }>" + ], + "path": "packages/kbn-reporting/export_types/csv/csv_searchsource.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/reporting-export-types-csv", + "id": "def-server.CsvSearchSourceExportType.createJob.$1", + "type": "CompoundType", + "tags": [], + "label": "jobParams", + "description": [], + "signature": [ + { + "pluginId": "@kbn/reporting-export-types-csv-common", + "scope": "common", + "docId": "kibKbnReportingExportTypesCsvCommonPluginApi", + "section": "def-common.JobParamsCSV", + "text": "JobParamsCSV" + } + ], + "path": "packages/kbn-reporting/export_types/csv/csv_searchsource.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/reporting-export-types-csv", + "id": "def-server.CsvSearchSourceExportType.runTask", + "type": "Function", + "tags": [], + "label": "runTask", + "description": [], + "signature": [ + "(jobId: string, job: ", + { + "pluginId": "@kbn/reporting-export-types-csv-common", + "scope": "common", + "docId": "kibKbnReportingExportTypesCsvCommonPluginApi", + "section": "def-common.TaskPayloadCSV", + "text": "TaskPayloadCSV" + }, + ", cancellationToken: ", + { + "pluginId": "@kbn/reporting-common", + "scope": "common", + "docId": "kibKbnReportingCommonPluginApi", + "section": "def-common.CancellationToken", + "text": "CancellationToken" + }, + ", stream: ", + "Writable", + ") => Promise<", + "TaskRunResult", + ">" + ], + "path": "packages/kbn-reporting/export_types/csv/csv_searchsource.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/reporting-export-types-csv", + "id": "def-server.CsvSearchSourceExportType.runTask.$1", + "type": "string", + "tags": [], + "label": "jobId", + "description": [], + "signature": [ + "string" + ], + "path": "packages/kbn-reporting/export_types/csv/csv_searchsource.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/reporting-export-types-csv", + "id": "def-server.CsvSearchSourceExportType.runTask.$2", + "type": "CompoundType", + "tags": [], + "label": "job", + "description": [], + "signature": [ + { + "pluginId": "@kbn/reporting-export-types-csv-common", + "scope": "common", + "docId": "kibKbnReportingExportTypesCsvCommonPluginApi", + "section": "def-common.TaskPayloadCSV", + "text": "TaskPayloadCSV" + } + ], + "path": "packages/kbn-reporting/export_types/csv/csv_searchsource.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/reporting-export-types-csv", + "id": "def-server.CsvSearchSourceExportType.runTask.$3", + "type": "Object", + "tags": [], + "label": "cancellationToken", + "description": [], + "signature": [ + { + "pluginId": "@kbn/reporting-common", + "scope": "common", + "docId": "kibKbnReportingCommonPluginApi", + "section": "def-common.CancellationToken", + "text": "CancellationToken" + } + ], + "path": "packages/kbn-reporting/export_types/csv/csv_searchsource.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/reporting-export-types-csv", + "id": "def-server.CsvSearchSourceExportType.runTask.$4", + "type": "Object", + "tags": [], + "label": "stream", + "description": [], + "signature": [ + "Writable" + ], + "path": "packages/kbn-reporting/export_types/csv/csv_searchsource.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/reporting-export-types-csv", + "id": "def-server.CsvSearchSourceImmediateExportType", + "type": "Class", + "tags": [], + "label": "CsvSearchSourceImmediateExportType", + "description": [], + "signature": [ + { + "pluginId": "@kbn/reporting-export-types-csv", + "scope": "server", + "docId": "kibKbnReportingExportTypesCsvPluginApi", + "section": "def-server.CsvSearchSourceImmediateExportType", + "text": "CsvSearchSourceImmediateExportType" + }, + " extends ", + { + "pluginId": "@kbn/reporting-server", + "scope": "server", + "docId": "kibKbnReportingServerPluginApi", + "section": "def-server.ExportType", + "text": "ExportType" + }, + "<", + { + "pluginId": "@kbn/reporting-export-types-csv-common", + "scope": "common", + "docId": "kibKbnReportingExportTypesCsvCommonPluginApi", + "section": "def-common.JobParamsDownloadCSV", + "text": "JobParamsDownloadCSV" + }, + ", ", + "ImmediateExecuteFn", + ", ", + { + "pluginId": "@kbn/reporting-server", + "scope": "server", + "docId": "kibKbnReportingServerPluginApi", + "section": "def-server.BaseExportTypeSetupDeps", + "text": "BaseExportTypeSetupDeps" + }, + ", CsvSearchSourceImmediateExportTypeStartDeps>" + ], + "path": "packages/kbn-reporting/export_types/csv/csv_searchsource_immediate.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/reporting-export-types-csv", + "id": "def-server.CsvSearchSourceImmediateExportType.id", + "type": "string", + "tags": [], + "label": "id", + "description": [], + "path": "packages/kbn-reporting/export_types/csv/csv_searchsource_immediate.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/reporting-export-types-csv", + "id": "def-server.CsvSearchSourceImmediateExportType.name", + "type": "string", + "tags": [], + "label": "name", + "description": [], + "path": "packages/kbn-reporting/export_types/csv/csv_searchsource_immediate.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/reporting-export-types-csv", + "id": "def-server.CsvSearchSourceImmediateExportType.jobType", + "type": "string", + "tags": [], + "label": "jobType", + "description": [], + "path": "packages/kbn-reporting/export_types/csv/csv_searchsource_immediate.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/reporting-export-types-csv", + "id": "def-server.CsvSearchSourceImmediateExportType.jobContentEncoding", + "type": "string", + "tags": [], + "label": "jobContentEncoding", + "description": [], + "signature": [ + "\"base64\"" + ], + "path": "packages/kbn-reporting/export_types/csv/csv_searchsource_immediate.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/reporting-export-types-csv", + "id": "def-server.CsvSearchSourceImmediateExportType.jobContentExtension", + "type": "string", + "tags": [], + "label": "jobContentExtension", + "description": [], + "signature": [ + "\"csv\"" + ], + "path": "packages/kbn-reporting/export_types/csv/csv_searchsource_immediate.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/reporting-export-types-csv", + "id": "def-server.CsvSearchSourceImmediateExportType.validLicenses", + "type": "Array", + "tags": [], + "label": "validLicenses", + "description": [], + "signature": [ + "(\"basic\" | \"standard\" | \"gold\" | \"platinum\" | \"enterprise\" | \"trial\")[]" + ], + "path": "packages/kbn-reporting/export_types/csv/csv_searchsource_immediate.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/reporting-export-types-csv", + "id": "def-server.CsvSearchSourceImmediateExportType.Unnamed", + "type": "Function", + "tags": [], + "label": "Constructor", + "description": [], + "signature": [ + "any" + ], + "path": "packages/kbn-reporting/export_types/csv/csv_searchsource_immediate.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/reporting-export-types-csv", + "id": "def-server.CsvSearchSourceImmediateExportType.Unnamed.$1", + "type": "Object", + "tags": [], + "label": "args", + "description": [], + "signature": [ + "[core: ", + { + "pluginId": "@kbn/core-lifecycle-server", + "scope": "common", + "docId": "kibKbnCoreLifecycleServerPluginApi", + "section": "def-common.CoreSetup", + "text": "CoreSetup" + }, + ", config: Readonly<{ encryptionKey?: string | undefined; } & { enabled: boolean; capture: Readonly<{} & { maxAttempts: number; }>; kibanaServer: Readonly<{ hostname?: string | undefined; protocol?: string | undefined; port?: number | undefined; } & {}>; queue: Readonly<{} & { timeout: number | moment.Duration; pollInterval: number | moment.Duration; indexInterval: string; pollEnabled: boolean; pollIntervalErrorMultiplier: number; }>; csv: Readonly<{} & { scroll: Readonly<{} & { duration: string; size: number; }>; checkForFormulas: boolean; escapeFormulaValues: boolean; enablePanelActionDownload: boolean; maxSizeBytes: number | ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ByteSizeValue", + "text": "ByteSizeValue" + }, + "; useByteOrderMarkEncoding: boolean; }>; roles: Readonly<{} & { enabled: boolean; allow: string[]; }>; poll: Readonly<{} & { jobCompletionNotifier: Readonly<{} & { interval: number; intervalErrorMultiplier: number; }>; jobsRefresh: Readonly<{} & { interval: number; intervalErrorMultiplier: number; }>; }>; export_types: Readonly<{} & { csv: Readonly<{} & { enabled: boolean; }>; png: Readonly<{} & { enabled: boolean; }>; pdf: Readonly<{} & { enabled: boolean; }>; }>; statefulSettings: Readonly<{} & { enabled: boolean; }>; }>, logger: ", + { + "pluginId": "@kbn/logging", + "scope": "common", + "docId": "kibKbnLoggingPluginApi", + "section": "def-common.Logger", + "text": "Logger" + }, + ", context: ", + { + "pluginId": "@kbn/core-plugins-server", + "scope": "common", + "docId": "kibKbnCorePluginsServerPluginApi", + "section": "def-common.PluginInitializerContext", + "text": "PluginInitializerContext" + }, + "; kibanaServer: Readonly<{ hostname?: string | undefined; protocol?: string | undefined; port?: number | undefined; } & {}>; queue: Readonly<{} & { timeout: number | moment.Duration; pollInterval: number | moment.Duration; indexInterval: string; pollEnabled: boolean; pollIntervalErrorMultiplier: number; }>; csv: Readonly<{} & { scroll: Readonly<{} & { duration: string; size: number; }>; checkForFormulas: boolean; escapeFormulaValues: boolean; enablePanelActionDownload: boolean; maxSizeBytes: number | ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ByteSizeValue", + "text": "ByteSizeValue" + }, + "; useByteOrderMarkEncoding: boolean; }>; roles: Readonly<{} & { enabled: boolean; allow: string[]; }>; poll: Readonly<{} & { jobCompletionNotifier: Readonly<{} & { interval: number; intervalErrorMultiplier: number; }>; jobsRefresh: Readonly<{} & { interval: number; intervalErrorMultiplier: number; }>; }>; export_types: Readonly<{} & { csv: Readonly<{} & { enabled: boolean; }>; png: Readonly<{} & { enabled: boolean; }>; pdf: Readonly<{} & { enabled: boolean; }>; }>; statefulSettings: Readonly<{} & { enabled: boolean; }>; }>>]" + ], + "path": "packages/kbn-reporting/export_types/csv/csv_searchsource_immediate.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/reporting-export-types-csv", + "id": "def-server.CsvSearchSourceImmediateExportType.createJob", + "type": "Function", + "tags": [], + "label": "createJob", + "description": [], + "signature": [ + "() => Promise" + ], + "path": "packages/kbn-reporting/export_types/csv/csv_searchsource_immediate.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/reporting-export-types-csv", + "id": "def-server.CsvSearchSourceImmediateExportType.runTask", + "type": "Function", + "tags": [], + "label": "runTask", + "description": [], + "signature": [ + "(_jobId: string | null, immediateJobParams: ", + { + "pluginId": "@kbn/reporting-export-types-csv-common", + "scope": "common", + "docId": "kibKbnReportingExportTypesCsvCommonPluginApi", + "section": "def-common.JobParamsDownloadCSV", + "text": "JobParamsDownloadCSV" + }, + ", context: ", + "ReportingRequestHandlerContext", + ", stream: ", + "Writable", + ", req: ", + { + "pluginId": "@kbn/core-http-server", + "scope": "common", + "docId": "kibKbnCoreHttpServerPluginApi", + "section": "def-common.KibanaRequest", + "text": "KibanaRequest" + }, + ") => Promise<", + "TaskRunResult", + ">" + ], + "path": "packages/kbn-reporting/export_types/csv/csv_searchsource_immediate.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/reporting-export-types-csv", + "id": "def-server.CsvSearchSourceImmediateExportType.runTask.$1", + "type": "CompoundType", + "tags": [], + "label": "_jobId", + "description": [], + "signature": [ + "string | null" + ], + "path": "packages/kbn-reporting/export_types/csv/csv_searchsource_immediate.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": false + }, + { + "parentPluginId": "@kbn/reporting-export-types-csv", + "id": "def-server.CsvSearchSourceImmediateExportType.runTask.$2", + "type": "Object", + "tags": [], + "label": "immediateJobParams", + "description": [], + "signature": [ + { + "pluginId": "@kbn/reporting-export-types-csv-common", + "scope": "common", + "docId": "kibKbnReportingExportTypesCsvCommonPluginApi", + "section": "def-common.JobParamsDownloadCSV", + "text": "JobParamsDownloadCSV" + } + ], + "path": "packages/kbn-reporting/export_types/csv/csv_searchsource_immediate.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/reporting-export-types-csv", + "id": "def-server.CsvSearchSourceImmediateExportType.runTask.$3", + "type": "CompoundType", + "tags": [], + "label": "context", + "description": [], + "signature": [ + "ReportingRequestHandlerContext" + ], + "path": "packages/kbn-reporting/export_types/csv/csv_searchsource_immediate.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/reporting-export-types-csv", + "id": "def-server.CsvSearchSourceImmediateExportType.runTask.$4", + "type": "Object", + "tags": [], + "label": "stream", + "description": [], + "signature": [ + "Writable" + ], + "path": "packages/kbn-reporting/export_types/csv/csv_searchsource_immediate.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/reporting-export-types-csv", + "id": "def-server.CsvSearchSourceImmediateExportType.runTask.$5", + "type": "Object", + "tags": [], + "label": "req", + "description": [], + "signature": [ + { + "pluginId": "@kbn/core-http-server", + "scope": "common", + "docId": "kibKbnCoreHttpServerPluginApi", + "section": "def-common.KibanaRequest", + "text": "KibanaRequest" + }, + "" + ], + "path": "packages/kbn-reporting/export_types/csv/csv_searchsource_immediate.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/reporting-export-types-csv", + "id": "def-server.CsvV2ExportType", + "type": "Class", + "tags": [], + "label": "CsvV2ExportType", + "description": [], + "signature": [ + { + "pluginId": "@kbn/reporting-export-types-csv", + "scope": "server", + "docId": "kibKbnReportingExportTypesCsvPluginApi", + "section": "def-server.CsvV2ExportType", + "text": "CsvV2ExportType" + }, + " extends ", + { + "pluginId": "@kbn/reporting-server", + "scope": "server", + "docId": "kibKbnReportingServerPluginApi", + "section": "def-server.ExportType", + "text": "ExportType" + }, + "<", + { + "pluginId": "@kbn/reporting-export-types-csv-common", + "scope": "common", + "docId": "kibKbnReportingExportTypesCsvCommonPluginApi", + "section": "def-common.JobParamsCsvFromSavedObject", + "text": "JobParamsCsvFromSavedObject" + }, + ", ", + { + "pluginId": "@kbn/reporting-export-types-csv-common", + "scope": "common", + "docId": "kibKbnReportingExportTypesCsvCommonPluginApi", + "section": "def-common.TaskPayloadCsvFromSavedObject", + "text": "TaskPayloadCsvFromSavedObject" + }, + ", ", + { + "pluginId": "@kbn/reporting-server", + "scope": "server", + "docId": "kibKbnReportingServerPluginApi", + "section": "def-server.BaseExportTypeSetupDeps", + "text": "BaseExportTypeSetupDeps" + }, + ", ", + "CsvV2ExportTypeStartDeps", + ">" + ], + "path": "packages/kbn-reporting/export_types/csv/csv_v2.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/reporting-export-types-csv", + "id": "def-server.CsvV2ExportType.id", + "type": "string", + "tags": [], + "label": "id", + "description": [], + "path": "packages/kbn-reporting/export_types/csv/csv_v2.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/reporting-export-types-csv", + "id": "def-server.CsvV2ExportType.name", + "type": "string", + "tags": [], + "label": "name", + "description": [], + "path": "packages/kbn-reporting/export_types/csv/csv_v2.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/reporting-export-types-csv", + "id": "def-server.CsvV2ExportType.jobType", + "type": "string", + "tags": [], + "label": "jobType", + "description": [], + "path": "packages/kbn-reporting/export_types/csv/csv_v2.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/reporting-export-types-csv", + "id": "def-server.CsvV2ExportType.jobContentEncoding", + "type": "string", + "tags": [], + "label": "jobContentEncoding", + "description": [], + "signature": [ + "\"base64\"" + ], + "path": "packages/kbn-reporting/export_types/csv/csv_v2.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/reporting-export-types-csv", + "id": "def-server.CsvV2ExportType.jobContentExtension", + "type": "string", + "tags": [], + "label": "jobContentExtension", + "description": [], + "signature": [ + "\"csv\"" + ], + "path": "packages/kbn-reporting/export_types/csv/csv_v2.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/reporting-export-types-csv", + "id": "def-server.CsvV2ExportType.validLicenses", + "type": "Array", + "tags": [], + "label": "validLicenses", + "description": [], + "signature": [ + "(\"basic\" | \"standard\" | \"gold\" | \"platinum\" | \"enterprise\" | \"trial\")[]" + ], + "path": "packages/kbn-reporting/export_types/csv/csv_v2.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/reporting-export-types-csv", + "id": "def-server.CsvV2ExportType.Unnamed", + "type": "Function", + "tags": [], + "label": "Constructor", + "description": [], + "signature": [ + "any" + ], + "path": "packages/kbn-reporting/export_types/csv/csv_v2.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/reporting-export-types-csv", + "id": "def-server.CsvV2ExportType.Unnamed.$1", + "type": "Object", + "tags": [], + "label": "args", + "description": [], + "signature": [ + "[core: ", + { + "pluginId": "@kbn/core-lifecycle-server", + "scope": "common", + "docId": "kibKbnCoreLifecycleServerPluginApi", + "section": "def-common.CoreSetup", + "text": "CoreSetup" + }, + ", config: Readonly<{ encryptionKey?: string | undefined; } & { enabled: boolean; capture: Readonly<{} & { maxAttempts: number; }>; kibanaServer: Readonly<{ hostname?: string | undefined; protocol?: string | undefined; port?: number | undefined; } & {}>; queue: Readonly<{} & { timeout: number | moment.Duration; pollInterval: number | moment.Duration; indexInterval: string; pollEnabled: boolean; pollIntervalErrorMultiplier: number; }>; csv: Readonly<{} & { scroll: Readonly<{} & { duration: string; size: number; }>; checkForFormulas: boolean; escapeFormulaValues: boolean; enablePanelActionDownload: boolean; maxSizeBytes: number | ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ByteSizeValue", + "text": "ByteSizeValue" + }, + "; useByteOrderMarkEncoding: boolean; }>; roles: Readonly<{} & { enabled: boolean; allow: string[]; }>; poll: Readonly<{} & { jobCompletionNotifier: Readonly<{} & { interval: number; intervalErrorMultiplier: number; }>; jobsRefresh: Readonly<{} & { interval: number; intervalErrorMultiplier: number; }>; }>; export_types: Readonly<{} & { csv: Readonly<{} & { enabled: boolean; }>; png: Readonly<{} & { enabled: boolean; }>; pdf: Readonly<{} & { enabled: boolean; }>; }>; statefulSettings: Readonly<{} & { enabled: boolean; }>; }>, logger: ", + { + "pluginId": "@kbn/logging", + "scope": "common", + "docId": "kibKbnLoggingPluginApi", + "section": "def-common.Logger", + "text": "Logger" + }, + ", context: ", + { + "pluginId": "@kbn/core-plugins-server", + "scope": "common", + "docId": "kibKbnCorePluginsServerPluginApi", + "section": "def-common.PluginInitializerContext", + "text": "PluginInitializerContext" + }, + "; kibanaServer: Readonly<{ hostname?: string | undefined; protocol?: string | undefined; port?: number | undefined; } & {}>; queue: Readonly<{} & { timeout: number | moment.Duration; pollInterval: number | moment.Duration; indexInterval: string; pollEnabled: boolean; pollIntervalErrorMultiplier: number; }>; csv: Readonly<{} & { scroll: Readonly<{} & { duration: string; size: number; }>; checkForFormulas: boolean; escapeFormulaValues: boolean; enablePanelActionDownload: boolean; maxSizeBytes: number | ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ByteSizeValue", + "text": "ByteSizeValue" + }, + "; useByteOrderMarkEncoding: boolean; }>; roles: Readonly<{} & { enabled: boolean; allow: string[]; }>; poll: Readonly<{} & { jobCompletionNotifier: Readonly<{} & { interval: number; intervalErrorMultiplier: number; }>; jobsRefresh: Readonly<{} & { interval: number; intervalErrorMultiplier: number; }>; }>; export_types: Readonly<{} & { csv: Readonly<{} & { enabled: boolean; }>; png: Readonly<{} & { enabled: boolean; }>; pdf: Readonly<{} & { enabled: boolean; }>; }>; statefulSettings: Readonly<{} & { enabled: boolean; }>; }>>]" + ], + "path": "packages/kbn-reporting/export_types/csv/csv_v2.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/reporting-export-types-csv", + "id": "def-server.CsvV2ExportType.createJob", + "type": "Function", + "tags": [], + "label": "createJob", + "description": [], + "signature": [ + "(jobParams: ", + { + "pluginId": "@kbn/reporting-export-types-csv-common", + "scope": "common", + "docId": "kibKbnReportingExportTypesCsvCommonPluginApi", + "section": "def-common.JobParamsCsvFromSavedObject", + "text": "JobParamsCsvFromSavedObject" + }, + ", _context: ", + "ReportingRequestHandlerContext", + ", req: ", + { + "pluginId": "@kbn/core-http-server", + "scope": "common", + "docId": "kibKbnCoreHttpServerPluginApi", + "section": "def-common.KibanaRequest", + "text": "KibanaRequest" + }, + ") => Promise<{ title: string; objectType: string; isDeprecated: boolean; version: string; layout?: { id?: ", + { + "pluginId": "screenshotting", + "scope": "common", + "docId": "kibScreenshottingPluginApi", + "section": "def-common.LayoutType", + "text": "LayoutType" + }, + " | undefined; dimensions?: { width: number; height: number; } | undefined; selectors?: Partial<", + "LayoutSelectorDictionary", + "> | undefined; zoom?: number | undefined; } | undefined; locatorParams: ", + "LocatorParams", + "<", + { + "pluginId": "@kbn/utility-types", + "scope": "common", + "docId": "kibKbnUtilityTypesPluginApi", + "section": "def-common.SerializableRecord", + "text": "SerializableRecord" + }, + ">[]; browserTimezone: string; }>" + ], + "path": "packages/kbn-reporting/export_types/csv/csv_v2.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/reporting-export-types-csv", + "id": "def-server.CsvV2ExportType.createJob.$1", + "type": "CompoundType", + "tags": [], + "label": "jobParams", + "description": [], + "signature": [ + { + "pluginId": "@kbn/reporting-export-types-csv-common", + "scope": "common", + "docId": "kibKbnReportingExportTypesCsvCommonPluginApi", + "section": "def-common.JobParamsCsvFromSavedObject", + "text": "JobParamsCsvFromSavedObject" + } + ], + "path": "packages/kbn-reporting/export_types/csv/csv_v2.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/reporting-export-types-csv", + "id": "def-server.CsvV2ExportType.createJob.$2", + "type": "CompoundType", + "tags": [], + "label": "_context", + "description": [], + "signature": [ + "ReportingRequestHandlerContext" + ], + "path": "packages/kbn-reporting/export_types/csv/csv_v2.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/reporting-export-types-csv", + "id": "def-server.CsvV2ExportType.createJob.$3", + "type": "Object", + "tags": [], + "label": "req", + "description": [], + "signature": [ + { + "pluginId": "@kbn/core-http-server", + "scope": "common", + "docId": "kibKbnCoreHttpServerPluginApi", + "section": "def-common.KibanaRequest", + "text": "KibanaRequest" + }, + "" + ], + "path": "packages/kbn-reporting/export_types/csv/csv_v2.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/reporting-export-types-csv", + "id": "def-server.CsvV2ExportType.runTask", + "type": "Function", + "tags": [], + "label": "runTask", + "description": [], + "signature": [ + "(jobId: string, job: ", + { + "pluginId": "@kbn/reporting-export-types-csv-common", + "scope": "common", + "docId": "kibKbnReportingExportTypesCsvCommonPluginApi", + "section": "def-common.TaskPayloadCsvFromSavedObject", + "text": "TaskPayloadCsvFromSavedObject" + }, + ", cancellationToken: ", + { + "pluginId": "@kbn/reporting-common", + "scope": "common", + "docId": "kibKbnReportingCommonPluginApi", + "section": "def-common.CancellationToken", + "text": "CancellationToken" + }, + ", stream: ", + "Writable", + ") => Promise<", + "TaskRunResult", + ">" + ], + "path": "packages/kbn-reporting/export_types/csv/csv_v2.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/reporting-export-types-csv", + "id": "def-server.CsvV2ExportType.runTask.$1", + "type": "string", + "tags": [], + "label": "jobId", + "description": [], + "signature": [ + "string" + ], + "path": "packages/kbn-reporting/export_types/csv/csv_v2.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/reporting-export-types-csv", + "id": "def-server.CsvV2ExportType.runTask.$2", + "type": "CompoundType", + "tags": [], + "label": "job", + "description": [], + "signature": [ + { + "pluginId": "@kbn/reporting-export-types-csv-common", + "scope": "common", + "docId": "kibKbnReportingExportTypesCsvCommonPluginApi", + "section": "def-common.TaskPayloadCsvFromSavedObject", + "text": "TaskPayloadCsvFromSavedObject" + } + ], + "path": "packages/kbn-reporting/export_types/csv/csv_v2.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/reporting-export-types-csv", + "id": "def-server.CsvV2ExportType.runTask.$3", + "type": "Object", + "tags": [], + "label": "cancellationToken", + "description": [], + "signature": [ + { + "pluginId": "@kbn/reporting-common", + "scope": "common", + "docId": "kibKbnReportingCommonPluginApi", + "section": "def-common.CancellationToken", + "text": "CancellationToken" + } + ], + "path": "packages/kbn-reporting/export_types/csv/csv_v2.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/reporting-export-types-csv", + "id": "def-server.CsvV2ExportType.runTask.$4", + "type": "Object", + "tags": [], + "label": "stream", + "description": [], + "signature": [ + "Writable" + ], + "path": "packages/kbn-reporting/export_types/csv/csv_v2.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + } + ], + "initialIsOpen": false + } + ], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] + }, + "common": { + "classes": [], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] + } +} \ No newline at end of file diff --git a/api_docs/kbn_reporting_export_types_csv.mdx b/api_docs/kbn_reporting_export_types_csv.mdx new file mode 100644 index 0000000000000..e59358e3bcaf7 --- /dev/null +++ b/api_docs/kbn_reporting_export_types_csv.mdx @@ -0,0 +1,30 @@ +--- +#### +#### 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: kibKbnReportingExportTypesCsvPluginApi +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: 2023-11-16 +tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/reporting-export-types-csv'] +--- +import kbnReportingExportTypesCsvObj from './kbn_reporting_export_types_csv.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 | +|-------------------|-----------|------------------------|-----------------| +| 50 | 0 | 50 | 3 | + +## Server + +### Classes + + diff --git a/api_docs/kbn_reporting_export_types_csv_common.devdocs.json b/api_docs/kbn_reporting_export_types_csv_common.devdocs.json new file mode 100644 index 0000000000000..4e6ff0c91e22c --- /dev/null +++ b/api_docs/kbn_reporting_export_types_csv_common.devdocs.json @@ -0,0 +1,358 @@ +{ + "id": "@kbn/reporting-export-types-csv-common", + "client": { + "classes": [], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] + }, + "server": { + "classes": [], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] + }, + "common": { + "classes": [], + "functions": [], + "interfaces": [ + { + "parentPluginId": "@kbn/reporting-export-types-csv-common", + "id": "def-common.JobParamsDownloadCSV", + "type": "Interface", + "tags": [], + "label": "JobParamsDownloadCSV", + "description": [], + "path": "packages/kbn-reporting/export_types/csv_common/index.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/reporting-export-types-csv-common", + "id": "def-common.JobParamsDownloadCSV.browserTimezone", + "type": "string", + "tags": [], + "label": "browserTimezone", + "description": [], + "path": "packages/kbn-reporting/export_types/csv_common/index.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/reporting-export-types-csv-common", + "id": "def-common.JobParamsDownloadCSV.title", + "type": "string", + "tags": [], + "label": "title", + "description": [], + "path": "packages/kbn-reporting/export_types/csv_common/index.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/reporting-export-types-csv-common", + "id": "def-common.JobParamsDownloadCSV.searchSource", + "type": "Object", + "tags": [], + "label": "searchSource", + "description": [], + "signature": [ + "{ type?: string | undefined; query?: ", + { + "pluginId": "@kbn/es-query", + "scope": "common", + "docId": "kibKbnEsQueryPluginApi", + "section": "def-common.Query", + "text": "Query" + }, + " | ", + { + "pluginId": "@kbn/es-query", + "scope": "common", + "docId": "kibKbnEsQueryPluginApi", + "section": "def-common.AggregateQuery", + "text": "AggregateQuery" + }, + " | undefined; filter?: ", + { + "pluginId": "@kbn/es-query", + "scope": "common", + "docId": "kibKbnEsQueryPluginApi", + "section": "def-common.Filter", + "text": "Filter" + }, + "[] | undefined; sort?: ", + { + "pluginId": "data", + "scope": "common", + "docId": "kibDataSearchPluginApi", + "section": "def-common.EsQuerySortValue", + "text": "EsQuerySortValue" + }, + "[] | undefined; highlight?: ", + { + "pluginId": "@kbn/utility-types", + "scope": "common", + "docId": "kibKbnUtilityTypesPluginApi", + "section": "def-common.SerializableRecord", + "text": "SerializableRecord" + }, + " | undefined; highlightAll?: boolean | undefined; trackTotalHits?: number | boolean | undefined; aggs?: { type: string; enabled?: boolean | undefined; id?: string | undefined; params?: {} | ", + { + "pluginId": "@kbn/utility-types", + "scope": "common", + "docId": "kibKbnUtilityTypesPluginApi", + "section": "def-common.SerializableRecord", + "text": "SerializableRecord" + }, + " | undefined; schema?: string | undefined; }[] | undefined; from?: number | undefined; size?: number | undefined; source?: boolean | ", + "Fields", + " | undefined; version?: boolean | undefined; fields?: ", + { + "pluginId": "data", + "scope": "common", + "docId": "kibDataSearchPluginApi", + "section": "def-common.SearchFieldValue", + "text": "SearchFieldValue" + }, + "[] | undefined; fieldsFromSource?: ", + "Fields", + " | undefined; index?: string | ", + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.DataViewSpec", + "text": "DataViewSpec" + }, + " | undefined; searchAfter?: ", + "SortResults", + " | undefined; timeout?: string | undefined; terminate_after?: number | undefined; parent?: ", + { + "pluginId": "data", + "scope": "common", + "docId": "kibDataSearchPluginApi", + "section": "def-common.SerializedSearchSourceFields", + "text": "SerializedSearchSourceFields" + }, + " | undefined; }" + ], + "path": "packages/kbn-reporting/export_types/csv_common/index.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/reporting-export-types-csv-common", + "id": "def-common.JobParamsDownloadCSV.columns", + "type": "Array", + "tags": [], + "label": "columns", + "description": [], + "signature": [ + "string[] | undefined" + ], + "path": "packages/kbn-reporting/export_types/csv_common/index.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + } + ], + "enums": [], + "misc": [ + { + "parentPluginId": "@kbn/reporting-export-types-csv-common", + "id": "def-common.CSV_JOB_TYPE", + "type": "string", + "tags": [], + "label": "CSV_JOB_TYPE", + "description": [], + "signature": [ + "\"csv_searchsource\"" + ], + "path": "packages/kbn-reporting/export_types/csv_common/constants.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/reporting-export-types-csv-common", + "id": "def-common.CSV_JOB_TYPE_DEPRECATED", + "type": "string", + "tags": [], + "label": "CSV_JOB_TYPE_DEPRECATED", + "description": [], + "signature": [ + "\"csv\"" + ], + "path": "packages/kbn-reporting/export_types/csv_common/index.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/reporting-export-types-csv-common", + "id": "def-common.CSV_JOB_TYPE_V2", + "type": "string", + "tags": [], + "label": "CSV_JOB_TYPE_V2", + "description": [], + "signature": [ + "\"csv_v2\"" + ], + "path": "packages/kbn-reporting/export_types/csv_common/constants.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/reporting-export-types-csv-common", + "id": "def-common.CSV_REPORT_TYPE", + "type": "string", + "tags": [], + "label": "CSV_REPORT_TYPE", + "description": [], + "signature": [ + "\"csv_searchsource\"" + ], + "path": "packages/kbn-reporting/export_types/csv_common/constants.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/reporting-export-types-csv-common", + "id": "def-common.CSV_REPORT_TYPE_DEPRECATED", + "type": "string", + "tags": [], + "label": "CSV_REPORT_TYPE_DEPRECATED", + "description": [], + "signature": [ + "\"CSV\"" + ], + "path": "packages/kbn-reporting/export_types/csv_common/index.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/reporting-export-types-csv-common", + "id": "def-common.CSV_REPORT_TYPE_V2", + "type": "string", + "tags": [], + "label": "CSV_REPORT_TYPE_V2", + "description": [], + "signature": [ + "\"csv_v2\"" + ], + "path": "packages/kbn-reporting/export_types/csv_common/constants.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/reporting-export-types-csv-common", + "id": "def-common.CSV_REPORTING_ACTION", + "type": "string", + "tags": [], + "label": "CSV_REPORTING_ACTION", + "description": [], + "signature": [ + "\"downloadCsvReport\"" + ], + "path": "packages/kbn-reporting/export_types/csv_common/index.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/reporting-export-types-csv-common", + "id": "def-common.CSV_SEARCHSOURCE_IMMEDIATE_TYPE", + "type": "string", + "tags": [], + "label": "CSV_SEARCHSOURCE_IMMEDIATE_TYPE", + "description": [], + "signature": [ + "\"csv_searchsource_immediate\"" + ], + "path": "packages/kbn-reporting/export_types/csv_common/index.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/reporting-export-types-csv-common", + "id": "def-common.JobParamsCSV", + "type": "Type", + "tags": [], + "label": "JobParamsCSV", + "description": [], + "signature": [ + "BaseParamsCSV & ", + "BaseParams" + ], + "path": "packages/kbn-reporting/export_types/csv_common/index.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/reporting-export-types-csv-common", + "id": "def-common.JobParamsCsvFromSavedObject", + "type": "Type", + "tags": [], + "label": "JobParamsCsvFromSavedObject", + "description": [ + "\nMakes title optional, as it can be derived from the saved search object" + ], + "signature": [ + "CsvFromSavedObjectBase & Omit<", + "BaseParamsV2", + ", \"title\"> & { title?: string | undefined; }" + ], + "path": "packages/kbn-reporting/export_types/csv_common/index.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/reporting-export-types-csv-common", + "id": "def-common.TaskPayloadCSV", + "type": "Type", + "tags": [], + "label": "TaskPayloadCSV", + "description": [], + "signature": [ + "BaseParamsCSV & ", + "BasePayload" + ], + "path": "packages/kbn-reporting/export_types/csv_common/index.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/reporting-export-types-csv-common", + "id": "def-common.TaskPayloadCsvFromSavedObject", + "type": "Type", + "tags": [], + "label": "TaskPayloadCsvFromSavedObject", + "description": [], + "signature": [ + "CsvFromSavedObjectBase & ", + "BasePayloadV2" + ], + "path": "packages/kbn-reporting/export_types/csv_common/index.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + } + ], + "objects": [] + } +} \ No newline at end of file diff --git a/api_docs/kbn_reporting_export_types_csv_common.mdx b/api_docs/kbn_reporting_export_types_csv_common.mdx new file mode 100644 index 0000000000000..19723d89f5871 --- /dev/null +++ b/api_docs/kbn_reporting_export_types_csv_common.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: kibKbnReportingExportTypesCsvCommonPluginApi +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: 2023-11-16 +tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/reporting-export-types-csv-common'] +--- +import kbnReportingExportTypesCsvCommonObj from './kbn_reporting_export_types_csv_common.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 | +|-------------------|-----------|------------------------|-----------------| +| 17 | 0 | 16 | 0 | + +## Common + +### Interfaces + + +### Consts, variables and types + + diff --git a/api_docs/kbn_reporting_export_types_pdf.devdocs.json b/api_docs/kbn_reporting_export_types_pdf.devdocs.json new file mode 100644 index 0000000000000..48dfb839ff109 --- /dev/null +++ b/api_docs/kbn_reporting_export_types_pdf.devdocs.json @@ -0,0 +1,806 @@ +{ + "id": "@kbn/reporting-export-types-pdf", + "client": { + "classes": [], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] + }, + "server": { + "classes": [ + { + "parentPluginId": "@kbn/reporting-export-types-pdf", + "id": "def-server.PdfExportType", + "type": "Class", + "tags": [], + "label": "PdfExportType", + "description": [], + "signature": [ + { + "pluginId": "@kbn/reporting-export-types-pdf", + "scope": "server", + "docId": "kibKbnReportingExportTypesPdfPluginApi", + "section": "def-server.PdfExportType", + "text": "PdfExportType" + }, + " extends ", + { + "pluginId": "@kbn/reporting-server", + "scope": "server", + "docId": "kibKbnReportingServerPluginApi", + "section": "def-server.ExportType", + "text": "ExportType" + }, + "<", + { + "pluginId": "@kbn/reporting-export-types-pdf-common", + "scope": "common", + "docId": "kibKbnReportingExportTypesPdfCommonPluginApi", + "section": "def-common.JobParamsPDFV2", + "text": "JobParamsPDFV2" + }, + ", ", + { + "pluginId": "@kbn/reporting-export-types-pdf-common", + "scope": "common", + "docId": "kibKbnReportingExportTypesPdfCommonPluginApi", + "section": "def-common.TaskPayloadPDFV2", + "text": "TaskPayloadPDFV2" + }, + ", ", + { + "pluginId": "@kbn/reporting-server", + "scope": "server", + "docId": "kibKbnReportingServerPluginApi", + "section": "def-server.BaseExportTypeSetupDeps", + "text": "BaseExportTypeSetupDeps" + }, + ", ", + { + "pluginId": "@kbn/reporting-server", + "scope": "server", + "docId": "kibKbnReportingServerPluginApi", + "section": "def-server.BaseExportTypeStartDeps", + "text": "BaseExportTypeStartDeps" + }, + ">" + ], + "path": "packages/kbn-reporting/export_types/pdf/printable_pdf_v2.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/reporting-export-types-pdf", + "id": "def-server.PdfExportType.id", + "type": "string", + "tags": [], + "label": "id", + "description": [], + "path": "packages/kbn-reporting/export_types/pdf/printable_pdf_v2.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/reporting-export-types-pdf", + "id": "def-server.PdfExportType.name", + "type": "string", + "tags": [], + "label": "name", + "description": [], + "path": "packages/kbn-reporting/export_types/pdf/printable_pdf_v2.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/reporting-export-types-pdf", + "id": "def-server.PdfExportType.jobType", + "type": "string", + "tags": [], + "label": "jobType", + "description": [], + "path": "packages/kbn-reporting/export_types/pdf/printable_pdf_v2.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/reporting-export-types-pdf", + "id": "def-server.PdfExportType.jobContentEncoding", + "type": "string", + "tags": [], + "label": "jobContentEncoding", + "description": [], + "signature": [ + "\"base64\"" + ], + "path": "packages/kbn-reporting/export_types/pdf/printable_pdf_v2.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/reporting-export-types-pdf", + "id": "def-server.PdfExportType.jobContentExtension", + "type": "string", + "tags": [], + "label": "jobContentExtension", + "description": [], + "signature": [ + "\"pdf\"" + ], + "path": "packages/kbn-reporting/export_types/pdf/printable_pdf_v2.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/reporting-export-types-pdf", + "id": "def-server.PdfExportType.validLicenses", + "type": "Array", + "tags": [], + "label": "validLicenses", + "description": [], + "signature": [ + "(\"standard\" | \"gold\" | \"platinum\" | \"enterprise\" | \"trial\")[]" + ], + "path": "packages/kbn-reporting/export_types/pdf/printable_pdf_v2.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/reporting-export-types-pdf", + "id": "def-server.PdfExportType.Unnamed", + "type": "Function", + "tags": [], + "label": "Constructor", + "description": [], + "signature": [ + "any" + ], + "path": "packages/kbn-reporting/export_types/pdf/printable_pdf_v2.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/reporting-export-types-pdf", + "id": "def-server.PdfExportType.Unnamed.$1", + "type": "Object", + "tags": [], + "label": "args", + "description": [], + "signature": [ + "[core: ", + { + "pluginId": "@kbn/core-lifecycle-server", + "scope": "common", + "docId": "kibKbnCoreLifecycleServerPluginApi", + "section": "def-common.CoreSetup", + "text": "CoreSetup" + }, + ", config: Readonly<{ encryptionKey?: string | undefined; } & { enabled: boolean; capture: Readonly<{} & { maxAttempts: number; }>; kibanaServer: Readonly<{ hostname?: string | undefined; protocol?: string | undefined; port?: number | undefined; } & {}>; queue: Readonly<{} & { timeout: number | moment.Duration; pollInterval: number | moment.Duration; indexInterval: string; pollEnabled: boolean; pollIntervalErrorMultiplier: number; }>; csv: Readonly<{} & { scroll: Readonly<{} & { duration: string; size: number; }>; checkForFormulas: boolean; escapeFormulaValues: boolean; enablePanelActionDownload: boolean; maxSizeBytes: number | ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ByteSizeValue", + "text": "ByteSizeValue" + }, + "; useByteOrderMarkEncoding: boolean; }>; roles: Readonly<{} & { enabled: boolean; allow: string[]; }>; poll: Readonly<{} & { jobCompletionNotifier: Readonly<{} & { interval: number; intervalErrorMultiplier: number; }>; jobsRefresh: Readonly<{} & { interval: number; intervalErrorMultiplier: number; }>; }>; export_types: Readonly<{} & { csv: Readonly<{} & { enabled: boolean; }>; png: Readonly<{} & { enabled: boolean; }>; pdf: Readonly<{} & { enabled: boolean; }>; }>; statefulSettings: Readonly<{} & { enabled: boolean; }>; }>, logger: ", + { + "pluginId": "@kbn/logging", + "scope": "common", + "docId": "kibKbnLoggingPluginApi", + "section": "def-common.Logger", + "text": "Logger" + }, + ", context: ", + { + "pluginId": "@kbn/core-plugins-server", + "scope": "common", + "docId": "kibKbnCorePluginsServerPluginApi", + "section": "def-common.PluginInitializerContext", + "text": "PluginInitializerContext" + }, + "; kibanaServer: Readonly<{ hostname?: string | undefined; protocol?: string | undefined; port?: number | undefined; } & {}>; queue: Readonly<{} & { timeout: number | moment.Duration; pollInterval: number | moment.Duration; indexInterval: string; pollEnabled: boolean; pollIntervalErrorMultiplier: number; }>; csv: Readonly<{} & { scroll: Readonly<{} & { duration: string; size: number; }>; checkForFormulas: boolean; escapeFormulaValues: boolean; enablePanelActionDownload: boolean; maxSizeBytes: number | ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ByteSizeValue", + "text": "ByteSizeValue" + }, + "; useByteOrderMarkEncoding: boolean; }>; roles: Readonly<{} & { enabled: boolean; allow: string[]; }>; poll: Readonly<{} & { jobCompletionNotifier: Readonly<{} & { interval: number; intervalErrorMultiplier: number; }>; jobsRefresh: Readonly<{} & { interval: number; intervalErrorMultiplier: number; }>; }>; export_types: Readonly<{} & { csv: Readonly<{} & { enabled: boolean; }>; png: Readonly<{} & { enabled: boolean; }>; pdf: Readonly<{} & { enabled: boolean; }>; }>; statefulSettings: Readonly<{} & { enabled: boolean; }>; }>>]" + ], + "path": "packages/kbn-reporting/export_types/pdf/printable_pdf_v2.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/reporting-export-types-pdf", + "id": "def-server.PdfExportType.createJob", + "type": "Function", + "tags": [], + "label": "createJob", + "description": [], + "signature": [ + "({ locatorParams, ...jobParams }: ", + { + "pluginId": "@kbn/reporting-export-types-pdf-common", + "scope": "common", + "docId": "kibKbnReportingExportTypesPdfCommonPluginApi", + "section": "def-common.JobParamsPDFV2", + "text": "JobParamsPDFV2" + }, + ") => Promise<{ locatorParams: ", + "LocatorParams", + "<", + { + "pluginId": "@kbn/utility-types", + "scope": "common", + "docId": "kibKbnUtilityTypesPluginApi", + "section": "def-common.SerializableRecord", + "text": "SerializableRecord" + }, + ">[]; isDeprecated: boolean; browserTimezone: string; forceNow: string; layout: { id?: ", + { + "pluginId": "screenshotting", + "scope": "common", + "docId": "kibScreenshottingPluginApi", + "section": "def-common.LayoutType", + "text": "LayoutType" + }, + " | undefined; dimensions?: { width: number; height: number; } | undefined; selectors?: Partial<", + "LayoutSelectorDictionary", + "> | undefined; zoom?: number | undefined; }; objectType: string; title: string; version: string; }>" + ], + "path": "packages/kbn-reporting/export_types/pdf/printable_pdf_v2.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/reporting-export-types-pdf", + "id": "def-server.PdfExportType.createJob.$1", + "type": "CompoundType", + "tags": [], + "label": "{ locatorParams, ...jobParams }", + "description": [], + "signature": [ + { + "pluginId": "@kbn/reporting-export-types-pdf-common", + "scope": "common", + "docId": "kibKbnReportingExportTypesPdfCommonPluginApi", + "section": "def-common.JobParamsPDFV2", + "text": "JobParamsPDFV2" + } + ], + "path": "packages/kbn-reporting/export_types/pdf/printable_pdf_v2.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [ + "jobParams" + ] + }, + { + "parentPluginId": "@kbn/reporting-export-types-pdf", + "id": "def-server.PdfExportType.runTask", + "type": "Function", + "tags": [], + "label": "runTask", + "description": [ + "\n" + ], + "signature": [ + "(jobId: string, payload: ", + { + "pluginId": "@kbn/reporting-export-types-pdf-common", + "scope": "common", + "docId": "kibKbnReportingExportTypesPdfCommonPluginApi", + "section": "def-common.TaskPayloadPDFV2", + "text": "TaskPayloadPDFV2" + }, + ", cancellationToken: ", + { + "pluginId": "@kbn/reporting-common", + "scope": "common", + "docId": "kibKbnReportingCommonPluginApi", + "section": "def-common.CancellationToken", + "text": "CancellationToken" + }, + ", stream: ", + "Writable", + ") => Promise<", + "TaskRunResult", + ">" + ], + "path": "packages/kbn-reporting/export_types/pdf/printable_pdf_v2.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/reporting-export-types-pdf", + "id": "def-server.PdfExportType.runTask.$1", + "type": "string", + "tags": [], + "label": "jobId", + "description": [], + "signature": [ + "string" + ], + "path": "packages/kbn-reporting/export_types/pdf/printable_pdf_v2.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/reporting-export-types-pdf", + "id": "def-server.PdfExportType.runTask.$2", + "type": "Object", + "tags": [], + "label": "payload", + "description": [], + "signature": [ + { + "pluginId": "@kbn/reporting-export-types-pdf-common", + "scope": "common", + "docId": "kibKbnReportingExportTypesPdfCommonPluginApi", + "section": "def-common.TaskPayloadPDFV2", + "text": "TaskPayloadPDFV2" + } + ], + "path": "packages/kbn-reporting/export_types/pdf/printable_pdf_v2.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/reporting-export-types-pdf", + "id": "def-server.PdfExportType.runTask.$3", + "type": "Object", + "tags": [], + "label": "cancellationToken", + "description": [], + "signature": [ + { + "pluginId": "@kbn/reporting-common", + "scope": "common", + "docId": "kibKbnReportingCommonPluginApi", + "section": "def-common.CancellationToken", + "text": "CancellationToken" + } + ], + "path": "packages/kbn-reporting/export_types/pdf/printable_pdf_v2.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/reporting-export-types-pdf", + "id": "def-server.PdfExportType.runTask.$4", + "type": "Object", + "tags": [], + "label": "stream", + "description": [], + "signature": [ + "Writable" + ], + "path": "packages/kbn-reporting/export_types/pdf/printable_pdf_v2.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/reporting-export-types-pdf", + "id": "def-server.PdfV1ExportType", + "type": "Class", + "tags": [ + "deprecated" + ], + "label": "PdfV1ExportType", + "description": [], + "signature": [ + { + "pluginId": "@kbn/reporting-export-types-pdf", + "scope": "server", + "docId": "kibKbnReportingExportTypesPdfPluginApi", + "section": "def-server.PdfV1ExportType", + "text": "PdfV1ExportType" + }, + " extends ", + { + "pluginId": "@kbn/reporting-server", + "scope": "server", + "docId": "kibKbnReportingServerPluginApi", + "section": "def-server.ExportType", + "text": "ExportType" + }, + "<", + { + "pluginId": "@kbn/reporting-export-types-pdf-common", + "scope": "common", + "docId": "kibKbnReportingExportTypesPdfCommonPluginApi", + "section": "def-common.JobParamsPDFDeprecated", + "text": "JobParamsPDFDeprecated" + }, + ", ", + { + "pluginId": "@kbn/reporting-export-types-pdf-common", + "scope": "common", + "docId": "kibKbnReportingExportTypesPdfCommonPluginApi", + "section": "def-common.TaskPayloadPDF", + "text": "TaskPayloadPDF" + }, + ", ", + { + "pluginId": "@kbn/reporting-server", + "scope": "server", + "docId": "kibKbnReportingServerPluginApi", + "section": "def-server.BaseExportTypeSetupDeps", + "text": "BaseExportTypeSetupDeps" + }, + ", ", + { + "pluginId": "@kbn/reporting-server", + "scope": "server", + "docId": "kibKbnReportingServerPluginApi", + "section": "def-server.BaseExportTypeStartDeps", + "text": "BaseExportTypeStartDeps" + }, + ">" + ], + "path": "packages/kbn-reporting/export_types/pdf/printable_pdf.ts", + "deprecated": true, + "trackAdoption": false, + "references": [ + { + "plugin": "reporting", + "path": "x-pack/plugins/reporting/server/core.ts" + }, + { + "plugin": "reporting", + "path": "x-pack/plugins/reporting/server/core.ts" + } + ], + "children": [ + { + "parentPluginId": "@kbn/reporting-export-types-pdf", + "id": "def-server.PdfV1ExportType.id", + "type": "string", + "tags": [], + "label": "id", + "description": [], + "path": "packages/kbn-reporting/export_types/pdf/printable_pdf.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/reporting-export-types-pdf", + "id": "def-server.PdfV1ExportType.name", + "type": "string", + "tags": [], + "label": "name", + "description": [], + "path": "packages/kbn-reporting/export_types/pdf/printable_pdf.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/reporting-export-types-pdf", + "id": "def-server.PdfV1ExportType.jobType", + "type": "string", + "tags": [], + "label": "jobType", + "description": [], + "path": "packages/kbn-reporting/export_types/pdf/printable_pdf.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/reporting-export-types-pdf", + "id": "def-server.PdfV1ExportType.jobContentEncoding", + "type": "string", + "tags": [], + "label": "jobContentEncoding", + "description": [], + "signature": [ + "\"base64\" | undefined" + ], + "path": "packages/kbn-reporting/export_types/pdf/printable_pdf.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/reporting-export-types-pdf", + "id": "def-server.PdfV1ExportType.jobContentExtension", + "type": "string", + "tags": [], + "label": "jobContentExtension", + "description": [], + "signature": [ + "\"pdf\"" + ], + "path": "packages/kbn-reporting/export_types/pdf/printable_pdf.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/reporting-export-types-pdf", + "id": "def-server.PdfV1ExportType.validLicenses", + "type": "Array", + "tags": [], + "label": "validLicenses", + "description": [], + "signature": [ + "(\"basic\" | \"standard\" | \"gold\" | \"platinum\" | \"enterprise\" | \"trial\")[]" + ], + "path": "packages/kbn-reporting/export_types/pdf/printable_pdf.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/reporting-export-types-pdf", + "id": "def-server.PdfV1ExportType.Unnamed", + "type": "Function", + "tags": [], + "label": "Constructor", + "description": [], + "signature": [ + "any" + ], + "path": "packages/kbn-reporting/export_types/pdf/printable_pdf.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/reporting-export-types-pdf", + "id": "def-server.PdfV1ExportType.Unnamed.$1", + "type": "Object", + "tags": [], + "label": "args", + "description": [], + "signature": [ + "[core: ", + { + "pluginId": "@kbn/core-lifecycle-server", + "scope": "common", + "docId": "kibKbnCoreLifecycleServerPluginApi", + "section": "def-common.CoreSetup", + "text": "CoreSetup" + }, + ", config: Readonly<{ encryptionKey?: string | undefined; } & { enabled: boolean; capture: Readonly<{} & { maxAttempts: number; }>; kibanaServer: Readonly<{ hostname?: string | undefined; protocol?: string | undefined; port?: number | undefined; } & {}>; queue: Readonly<{} & { timeout: number | moment.Duration; pollInterval: number | moment.Duration; indexInterval: string; pollEnabled: boolean; pollIntervalErrorMultiplier: number; }>; csv: Readonly<{} & { scroll: Readonly<{} & { duration: string; size: number; }>; checkForFormulas: boolean; escapeFormulaValues: boolean; enablePanelActionDownload: boolean; maxSizeBytes: number | ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ByteSizeValue", + "text": "ByteSizeValue" + }, + "; useByteOrderMarkEncoding: boolean; }>; roles: Readonly<{} & { enabled: boolean; allow: string[]; }>; poll: Readonly<{} & { jobCompletionNotifier: Readonly<{} & { interval: number; intervalErrorMultiplier: number; }>; jobsRefresh: Readonly<{} & { interval: number; intervalErrorMultiplier: number; }>; }>; export_types: Readonly<{} & { csv: Readonly<{} & { enabled: boolean; }>; png: Readonly<{} & { enabled: boolean; }>; pdf: Readonly<{} & { enabled: boolean; }>; }>; statefulSettings: Readonly<{} & { enabled: boolean; }>; }>, logger: ", + { + "pluginId": "@kbn/logging", + "scope": "common", + "docId": "kibKbnLoggingPluginApi", + "section": "def-common.Logger", + "text": "Logger" + }, + ", context: ", + { + "pluginId": "@kbn/core-plugins-server", + "scope": "common", + "docId": "kibKbnCorePluginsServerPluginApi", + "section": "def-common.PluginInitializerContext", + "text": "PluginInitializerContext" + }, + "; kibanaServer: Readonly<{ hostname?: string | undefined; protocol?: string | undefined; port?: number | undefined; } & {}>; queue: Readonly<{} & { timeout: number | moment.Duration; pollInterval: number | moment.Duration; indexInterval: string; pollEnabled: boolean; pollIntervalErrorMultiplier: number; }>; csv: Readonly<{} & { scroll: Readonly<{} & { duration: string; size: number; }>; checkForFormulas: boolean; escapeFormulaValues: boolean; enablePanelActionDownload: boolean; maxSizeBytes: number | ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ByteSizeValue", + "text": "ByteSizeValue" + }, + "; useByteOrderMarkEncoding: boolean; }>; roles: Readonly<{} & { enabled: boolean; allow: string[]; }>; poll: Readonly<{} & { jobCompletionNotifier: Readonly<{} & { interval: number; intervalErrorMultiplier: number; }>; jobsRefresh: Readonly<{} & { interval: number; intervalErrorMultiplier: number; }>; }>; export_types: Readonly<{} & { csv: Readonly<{} & { enabled: boolean; }>; png: Readonly<{} & { enabled: boolean; }>; pdf: Readonly<{} & { enabled: boolean; }>; }>; statefulSettings: Readonly<{} & { enabled: boolean; }>; }>>]" + ], + "path": "packages/kbn-reporting/export_types/pdf/printable_pdf.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/reporting-export-types-pdf", + "id": "def-server.PdfV1ExportType.createJob", + "type": "Function", + "tags": [], + "label": "createJob", + "description": [], + "signature": [ + "({ relativeUrls, ...jobParams }: ", + { + "pluginId": "@kbn/reporting-export-types-pdf-common", + "scope": "common", + "docId": "kibKbnReportingExportTypesPdfCommonPluginApi", + "section": "def-common.JobParamsPDFDeprecated", + "text": "JobParamsPDFDeprecated" + }, + ") => Promise<{ isDeprecated: boolean; forceNow: string; objects: { relativeUrl: string; }[]; layout: { id?: ", + { + "pluginId": "screenshotting", + "scope": "common", + "docId": "kibScreenshottingPluginApi", + "section": "def-common.LayoutType", + "text": "LayoutType" + }, + " | undefined; dimensions?: { width: number; height: number; } | undefined; selectors?: Partial<", + "LayoutSelectorDictionary", + "> | undefined; zoom?: number | undefined; }; objectType: string; title: string; browserTimezone: string; version: string; }>" + ], + "path": "packages/kbn-reporting/export_types/pdf/printable_pdf.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/reporting-export-types-pdf", + "id": "def-server.PdfV1ExportType.createJob.$1", + "type": "CompoundType", + "tags": [], + "label": "{ relativeUrls, ...jobParams }", + "description": [], + "signature": [ + { + "pluginId": "@kbn/reporting-export-types-pdf-common", + "scope": "common", + "docId": "kibKbnReportingExportTypesPdfCommonPluginApi", + "section": "def-common.JobParamsPDFDeprecated", + "text": "JobParamsPDFDeprecated" + } + ], + "path": "packages/kbn-reporting/export_types/pdf/printable_pdf.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/reporting-export-types-pdf", + "id": "def-server.PdfV1ExportType.runTask", + "type": "Function", + "tags": [], + "label": "runTask", + "description": [], + "signature": [ + "(jobId: string, job: ", + { + "pluginId": "@kbn/reporting-export-types-pdf-common", + "scope": "common", + "docId": "kibKbnReportingExportTypesPdfCommonPluginApi", + "section": "def-common.TaskPayloadPDF", + "text": "TaskPayloadPDF" + }, + ", cancellationToken: ", + { + "pluginId": "@kbn/reporting-common", + "scope": "common", + "docId": "kibKbnReportingCommonPluginApi", + "section": "def-common.CancellationToken", + "text": "CancellationToken" + }, + ", stream: ", + "Writable", + ") => Promise<", + "TaskRunResult", + ">" + ], + "path": "packages/kbn-reporting/export_types/pdf/printable_pdf.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/reporting-export-types-pdf", + "id": "def-server.PdfV1ExportType.runTask.$1", + "type": "string", + "tags": [], + "label": "jobId", + "description": [], + "signature": [ + "string" + ], + "path": "packages/kbn-reporting/export_types/pdf/printable_pdf.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/reporting-export-types-pdf", + "id": "def-server.PdfV1ExportType.runTask.$2", + "type": "Object", + "tags": [], + "label": "job", + "description": [], + "signature": [ + { + "pluginId": "@kbn/reporting-export-types-pdf-common", + "scope": "common", + "docId": "kibKbnReportingExportTypesPdfCommonPluginApi", + "section": "def-common.TaskPayloadPDF", + "text": "TaskPayloadPDF" + } + ], + "path": "packages/kbn-reporting/export_types/pdf/printable_pdf.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/reporting-export-types-pdf", + "id": "def-server.PdfV1ExportType.runTask.$3", + "type": "Object", + "tags": [], + "label": "cancellationToken", + "description": [], + "signature": [ + { + "pluginId": "@kbn/reporting-common", + "scope": "common", + "docId": "kibKbnReportingCommonPluginApi", + "section": "def-common.CancellationToken", + "text": "CancellationToken" + } + ], + "path": "packages/kbn-reporting/export_types/pdf/printable_pdf.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/reporting-export-types-pdf", + "id": "def-server.PdfV1ExportType.runTask.$4", + "type": "Object", + "tags": [], + "label": "stream", + "description": [], + "signature": [ + "Writable" + ], + "path": "packages/kbn-reporting/export_types/pdf/printable_pdf.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + } + ], + "initialIsOpen": false + } + ], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] + }, + "common": { + "classes": [], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] + } +} \ No newline at end of file diff --git a/api_docs/kbn_reporting_export_types_pdf.mdx b/api_docs/kbn_reporting_export_types_pdf.mdx new file mode 100644 index 0000000000000..6112c4f0bfc3b --- /dev/null +++ b/api_docs/kbn_reporting_export_types_pdf.mdx @@ -0,0 +1,30 @@ +--- +#### +#### 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: kibKbnReportingExportTypesPdfPluginApi +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: 2023-11-16 +tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/reporting-export-types-pdf'] +--- +import kbnReportingExportTypesPdfObj from './kbn_reporting_export_types_pdf.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 | +|-------------------|-----------|------------------------|-----------------| +| 32 | 0 | 31 | 0 | + +## Server + +### Classes + + diff --git a/api_docs/kbn_reporting_export_types_pdf_common.devdocs.json b/api_docs/kbn_reporting_export_types_pdf_common.devdocs.json new file mode 100644 index 0000000000000..335e4e24dbd67 --- /dev/null +++ b/api_docs/kbn_reporting_export_types_pdf_common.devdocs.json @@ -0,0 +1,324 @@ +{ + "id": "@kbn/reporting-export-types-pdf-common", + "client": { + "classes": [], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] + }, + "server": { + "classes": [], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] + }, + "common": { + "classes": [], + "functions": [], + "interfaces": [ + { + "parentPluginId": "@kbn/reporting-export-types-pdf-common", + "id": "def-common.TaskPayloadPDF", + "type": "Interface", + "tags": [], + "label": "TaskPayloadPDF", + "description": [ + "\nStructure of stored job data provided by create_job" + ], + "signature": [ + { + "pluginId": "@kbn/reporting-export-types-pdf-common", + "scope": "common", + "docId": "kibKbnReportingExportTypesPdfCommonPluginApi", + "section": "def-common.TaskPayloadPDF", + "text": "TaskPayloadPDF" + }, + " extends ", + "BasePayload" + ], + "path": "packages/kbn-reporting/export_types/pdf_common/index.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/reporting-export-types-pdf-common", + "id": "def-common.TaskPayloadPDF.layout", + "type": "Object", + "tags": [], + "label": "layout", + "description": [], + "signature": [ + "{ id?: ", + { + "pluginId": "screenshotting", + "scope": "common", + "docId": "kibScreenshottingPluginApi", + "section": "def-common.LayoutType", + "text": "LayoutType" + }, + " | undefined; dimensions?: { width: number; height: number; } | undefined; selectors?: Partial<", + "LayoutSelectorDictionary", + "> | undefined; zoom?: number | undefined; }" + ], + "path": "packages/kbn-reporting/export_types/pdf_common/index.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/reporting-export-types-pdf-common", + "id": "def-common.TaskPayloadPDF.forceNow", + "type": "string", + "tags": [], + "label": "forceNow", + "description": [], + "signature": [ + "string | undefined" + ], + "path": "packages/kbn-reporting/export_types/pdf_common/index.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/reporting-export-types-pdf-common", + "id": "def-common.TaskPayloadPDF.objects", + "type": "Array", + "tags": [], + "label": "objects", + "description": [], + "signature": [ + "{ relativeUrl: string; }[]" + ], + "path": "packages/kbn-reporting/export_types/pdf_common/index.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/reporting-export-types-pdf-common", + "id": "def-common.TaskPayloadPDFV2", + "type": "Interface", + "tags": [], + "label": "TaskPayloadPDFV2", + "description": [], + "signature": [ + { + "pluginId": "@kbn/reporting-export-types-pdf-common", + "scope": "common", + "docId": "kibKbnReportingExportTypesPdfCommonPluginApi", + "section": "def-common.TaskPayloadPDFV2", + "text": "TaskPayloadPDFV2" + }, + " extends ", + "BasePayload", + ",BaseParamsPDFV2" + ], + "path": "packages/kbn-reporting/export_types/pdf_common/index.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/reporting-export-types-pdf-common", + "id": "def-common.TaskPayloadPDFV2.layout", + "type": "Object", + "tags": [], + "label": "layout", + "description": [], + "signature": [ + "{ id?: ", + { + "pluginId": "screenshotting", + "scope": "common", + "docId": "kibScreenshottingPluginApi", + "section": "def-common.LayoutType", + "text": "LayoutType" + }, + " | undefined; dimensions?: { width: number; height: number; } | undefined; selectors?: Partial<", + "LayoutSelectorDictionary", + "> | undefined; zoom?: number | undefined; }" + ], + "path": "packages/kbn-reporting/export_types/pdf_common/index.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/reporting-export-types-pdf-common", + "id": "def-common.TaskPayloadPDFV2.forceNow", + "type": "string", + "tags": [], + "label": "forceNow", + "description": [ + "\nThe value of forceNow is injected server-side every time a given report is generated." + ], + "path": "packages/kbn-reporting/export_types/pdf_common/index.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + } + ], + "enums": [], + "misc": [ + { + "parentPluginId": "@kbn/reporting-export-types-pdf-common", + "id": "def-common.JobAppParamsPDFV2", + "type": "Type", + "tags": [], + "label": "JobAppParamsPDFV2", + "description": [ + "\nPublic-facing interface\nApps should use this interface to build job params.\nbrowserTimezone and version is provided by Reporting" + ], + "signature": [ + "{ title: string; layout: { id?: ", + { + "pluginId": "screenshotting", + "scope": "common", + "docId": "kibScreenshottingPluginApi", + "section": "def-common.LayoutType", + "text": "LayoutType" + }, + " | undefined; dimensions?: { width: number; height: number; } | undefined; selectors?: Partial<", + "LayoutSelectorDictionary", + "> | undefined; zoom?: number | undefined; }; locatorParams: ", + "LocatorParams", + "<", + { + "pluginId": "@kbn/utility-types", + "scope": "common", + "docId": "kibKbnUtilityTypesPluginApi", + "section": "def-common.SerializableRecord", + "text": "SerializableRecord" + }, + ">[]; objectType: string; }" + ], + "path": "packages/kbn-reporting/export_types/pdf_common/index.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/reporting-export-types-pdf-common", + "id": "def-common.JobParamsPDFDeprecated", + "type": "Type", + "tags": [ + "deprecated" + ], + "label": "JobParamsPDFDeprecated", + "description": [], + "signature": [ + "BaseParamsPDF & ", + "BaseParams" + ], + "path": "packages/kbn-reporting/export_types/pdf_common/index.ts", + "deprecated": true, + "trackAdoption": false, + "references": [ + { + "plugin": "@kbn/reporting-export-types-pdf", + "path": "packages/kbn-reporting/export_types/pdf/printable_pdf.ts" + }, + { + "plugin": "@kbn/reporting-export-types-pdf", + "path": "packages/kbn-reporting/export_types/pdf/printable_pdf.ts" + }, + { + "plugin": "@kbn/reporting-export-types-pdf", + "path": "packages/kbn-reporting/export_types/pdf/printable_pdf.ts" + }, + { + "plugin": "reporting", + "path": "x-pack/plugins/reporting/server/routes/common/generate/request_handler.test.ts" + }, + { + "plugin": "reporting", + "path": "x-pack/plugins/reporting/server/routes/common/generate/request_handler.test.ts" + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/reporting-export-types-pdf-common", + "id": "def-common.JobParamsPDFV2", + "type": "Type", + "tags": [], + "label": "JobParamsPDFV2", + "description": [], + "signature": [ + "BaseParamsPDFV2 & ", + "BaseParams" + ], + "path": "packages/kbn-reporting/export_types/pdf_common/index.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/reporting-export-types-pdf-common", + "id": "def-common.PDF_JOB_TYPE", + "type": "string", + "tags": [], + "label": "PDF_JOB_TYPE", + "description": [], + "signature": [ + "\"printable_pdf\"" + ], + "path": "packages/kbn-reporting/export_types/pdf_common/constants.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/reporting-export-types-pdf-common", + "id": "def-common.PDF_JOB_TYPE_V2", + "type": "string", + "tags": [], + "label": "PDF_JOB_TYPE_V2", + "description": [], + "signature": [ + "\"printable_pdf_v2\"" + ], + "path": "packages/kbn-reporting/export_types/pdf_common/constants.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/reporting-export-types-pdf-common", + "id": "def-common.PDF_REPORT_TYPE", + "type": "string", + "tags": [], + "label": "PDF_REPORT_TYPE", + "description": [], + "signature": [ + "\"printablePdf\"" + ], + "path": "packages/kbn-reporting/export_types/pdf_common/constants.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/reporting-export-types-pdf-common", + "id": "def-common.PDF_REPORT_TYPE_V2", + "type": "string", + "tags": [], + "label": "PDF_REPORT_TYPE_V2", + "description": [], + "signature": [ + "\"printablePdfV2\"" + ], + "path": "packages/kbn-reporting/export_types/pdf_common/constants.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + } + ], + "objects": [] + } +} \ No newline at end of file diff --git a/api_docs/kbn_reporting_export_types_pdf_common.mdx b/api_docs/kbn_reporting_export_types_pdf_common.mdx new file mode 100644 index 0000000000000..e80e700bd2cf9 --- /dev/null +++ b/api_docs/kbn_reporting_export_types_pdf_common.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: kibKbnReportingExportTypesPdfCommonPluginApi +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: 2023-11-16 +tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/reporting-export-types-pdf-common'] +--- +import kbnReportingExportTypesPdfCommonObj from './kbn_reporting_export_types_pdf_common.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 | +|-------------------|-----------|------------------------|-----------------| +| 14 | 0 | 11 | 0 | + +## Common + +### Interfaces + + +### Consts, variables and types + + diff --git a/api_docs/kbn_reporting_export_types_png.devdocs.json b/api_docs/kbn_reporting_export_types_png.devdocs.json new file mode 100644 index 0000000000000..176277a8cf6ec --- /dev/null +++ b/api_docs/kbn_reporting_export_types_png.devdocs.json @@ -0,0 +1,420 @@ +{ + "id": "@kbn/reporting-export-types-png", + "client": { + "classes": [], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] + }, + "server": { + "classes": [ + { + "parentPluginId": "@kbn/reporting-export-types-png", + "id": "def-server.PngExportType", + "type": "Class", + "tags": [], + "label": "PngExportType", + "description": [], + "signature": [ + { + "pluginId": "@kbn/reporting-export-types-png", + "scope": "server", + "docId": "kibKbnReportingExportTypesPngPluginApi", + "section": "def-server.PngExportType", + "text": "PngExportType" + }, + " extends ", + { + "pluginId": "@kbn/reporting-server", + "scope": "server", + "docId": "kibKbnReportingServerPluginApi", + "section": "def-server.ExportType", + "text": "ExportType" + }, + "<", + { + "pluginId": "@kbn/reporting-export-types-png-common", + "scope": "common", + "docId": "kibKbnReportingExportTypesPngCommonPluginApi", + "section": "def-common.JobParamsPNGV2", + "text": "JobParamsPNGV2" + }, + ", ", + { + "pluginId": "@kbn/reporting-export-types-png-common", + "scope": "common", + "docId": "kibKbnReportingExportTypesPngCommonPluginApi", + "section": "def-common.TaskPayloadPNGV2", + "text": "TaskPayloadPNGV2" + }, + ", ", + { + "pluginId": "@kbn/reporting-server", + "scope": "server", + "docId": "kibKbnReportingServerPluginApi", + "section": "def-server.BaseExportTypeSetupDeps", + "text": "BaseExportTypeSetupDeps" + }, + ", ", + { + "pluginId": "@kbn/reporting-server", + "scope": "server", + "docId": "kibKbnReportingServerPluginApi", + "section": "def-server.BaseExportTypeStartDeps", + "text": "BaseExportTypeStartDeps" + }, + ">" + ], + "path": "packages/kbn-reporting/export_types/png/png_v2.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/reporting-export-types-png", + "id": "def-server.PngExportType.id", + "type": "string", + "tags": [], + "label": "id", + "description": [], + "path": "packages/kbn-reporting/export_types/png/png_v2.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/reporting-export-types-png", + "id": "def-server.PngExportType.name", + "type": "string", + "tags": [], + "label": "name", + "description": [], + "path": "packages/kbn-reporting/export_types/png/png_v2.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/reporting-export-types-png", + "id": "def-server.PngExportType.jobType", + "type": "string", + "tags": [], + "label": "jobType", + "description": [], + "path": "packages/kbn-reporting/export_types/png/png_v2.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/reporting-export-types-png", + "id": "def-server.PngExportType.jobContentEncoding", + "type": "string", + "tags": [], + "label": "jobContentEncoding", + "description": [], + "signature": [ + "\"base64\"" + ], + "path": "packages/kbn-reporting/export_types/png/png_v2.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/reporting-export-types-png", + "id": "def-server.PngExportType.jobContentExtension", + "type": "string", + "tags": [], + "label": "jobContentExtension", + "description": [], + "signature": [ + "\"png\"" + ], + "path": "packages/kbn-reporting/export_types/png/png_v2.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/reporting-export-types-png", + "id": "def-server.PngExportType.validLicenses", + "type": "Array", + "tags": [], + "label": "validLicenses", + "description": [], + "signature": [ + "(\"basic\" | \"standard\" | \"gold\" | \"platinum\" | \"enterprise\" | \"trial\")[]" + ], + "path": "packages/kbn-reporting/export_types/png/png_v2.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/reporting-export-types-png", + "id": "def-server.PngExportType.Unnamed", + "type": "Function", + "tags": [], + "label": "Constructor", + "description": [], + "signature": [ + "any" + ], + "path": "packages/kbn-reporting/export_types/png/png_v2.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/reporting-export-types-png", + "id": "def-server.PngExportType.Unnamed.$1", + "type": "Object", + "tags": [], + "label": "args", + "description": [], + "signature": [ + "[core: ", + { + "pluginId": "@kbn/core-lifecycle-server", + "scope": "common", + "docId": "kibKbnCoreLifecycleServerPluginApi", + "section": "def-common.CoreSetup", + "text": "CoreSetup" + }, + ", config: Readonly<{ encryptionKey?: string | undefined; } & { enabled: boolean; capture: Readonly<{} & { maxAttempts: number; }>; kibanaServer: Readonly<{ hostname?: string | undefined; protocol?: string | undefined; port?: number | undefined; } & {}>; queue: Readonly<{} & { timeout: number | moment.Duration; pollInterval: number | moment.Duration; indexInterval: string; pollEnabled: boolean; pollIntervalErrorMultiplier: number; }>; csv: Readonly<{} & { scroll: Readonly<{} & { duration: string; size: number; }>; checkForFormulas: boolean; escapeFormulaValues: boolean; enablePanelActionDownload: boolean; maxSizeBytes: number | ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ByteSizeValue", + "text": "ByteSizeValue" + }, + "; useByteOrderMarkEncoding: boolean; }>; roles: Readonly<{} & { enabled: boolean; allow: string[]; }>; poll: Readonly<{} & { jobCompletionNotifier: Readonly<{} & { interval: number; intervalErrorMultiplier: number; }>; jobsRefresh: Readonly<{} & { interval: number; intervalErrorMultiplier: number; }>; }>; export_types: Readonly<{} & { csv: Readonly<{} & { enabled: boolean; }>; png: Readonly<{} & { enabled: boolean; }>; pdf: Readonly<{} & { enabled: boolean; }>; }>; statefulSettings: Readonly<{} & { enabled: boolean; }>; }>, logger: ", + { + "pluginId": "@kbn/logging", + "scope": "common", + "docId": "kibKbnLoggingPluginApi", + "section": "def-common.Logger", + "text": "Logger" + }, + ", context: ", + { + "pluginId": "@kbn/core-plugins-server", + "scope": "common", + "docId": "kibKbnCorePluginsServerPluginApi", + "section": "def-common.PluginInitializerContext", + "text": "PluginInitializerContext" + }, + "; kibanaServer: Readonly<{ hostname?: string | undefined; protocol?: string | undefined; port?: number | undefined; } & {}>; queue: Readonly<{} & { timeout: number | moment.Duration; pollInterval: number | moment.Duration; indexInterval: string; pollEnabled: boolean; pollIntervalErrorMultiplier: number; }>; csv: Readonly<{} & { scroll: Readonly<{} & { duration: string; size: number; }>; checkForFormulas: boolean; escapeFormulaValues: boolean; enablePanelActionDownload: boolean; maxSizeBytes: number | ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ByteSizeValue", + "text": "ByteSizeValue" + }, + "; useByteOrderMarkEncoding: boolean; }>; roles: Readonly<{} & { enabled: boolean; allow: string[]; }>; poll: Readonly<{} & { jobCompletionNotifier: Readonly<{} & { interval: number; intervalErrorMultiplier: number; }>; jobsRefresh: Readonly<{} & { interval: number; intervalErrorMultiplier: number; }>; }>; export_types: Readonly<{} & { csv: Readonly<{} & { enabled: boolean; }>; png: Readonly<{} & { enabled: boolean; }>; pdf: Readonly<{} & { enabled: boolean; }>; }>; statefulSettings: Readonly<{} & { enabled: boolean; }>; }>>]" + ], + "path": "packages/kbn-reporting/export_types/png/png_v2.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/reporting-export-types-png", + "id": "def-server.PngExportType.createJob", + "type": "Function", + "tags": [ + "params" + ], + "label": "createJob", + "description": [], + "signature": [ + "({ locatorParams, ...jobParams }: ", + { + "pluginId": "@kbn/reporting-export-types-png-common", + "scope": "common", + "docId": "kibKbnReportingExportTypesPngCommonPluginApi", + "section": "def-common.JobParamsPNGV2", + "text": "JobParamsPNGV2" + }, + ") => Promise<{ locatorParams: ", + "LocatorParams", + "<", + { + "pluginId": "@kbn/utility-types", + "scope": "common", + "docId": "kibKbnUtilityTypesPluginApi", + "section": "def-common.SerializableRecord", + "text": "SerializableRecord" + }, + ">[]; isDeprecated: boolean; browserTimezone: string; forceNow: string; layout: { id?: ", + { + "pluginId": "screenshotting", + "scope": "common", + "docId": "kibScreenshottingPluginApi", + "section": "def-common.LayoutType", + "text": "LayoutType" + }, + " | undefined; dimensions?: { width: number; height: number; } | undefined; selectors?: Partial<", + "LayoutSelectorDictionary", + "> | undefined; zoom?: number | undefined; }; objectType: string; title: string; version: string; }>" + ], + "path": "packages/kbn-reporting/export_types/png/png_v2.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/reporting-export-types-png", + "id": "def-server.PngExportType.createJob.$1", + "type": "Object", + "tags": [], + "label": "{ locatorParams, ...jobParams }", + "description": [], + "signature": [ + { + "pluginId": "@kbn/reporting-export-types-png-common", + "scope": "common", + "docId": "kibKbnReportingExportTypesPngCommonPluginApi", + "section": "def-common.JobParamsPNGV2", + "text": "JobParamsPNGV2" + } + ], + "path": "packages/kbn-reporting/export_types/png/png_v2.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [ + "jobParams" + ] + }, + { + "parentPluginId": "@kbn/reporting-export-types-png", + "id": "def-server.PngExportType.runTask", + "type": "Function", + "tags": [], + "label": "runTask", + "description": [ + "\n" + ], + "signature": [ + "(jobId: string, payload: ", + { + "pluginId": "@kbn/reporting-export-types-png-common", + "scope": "common", + "docId": "kibKbnReportingExportTypesPngCommonPluginApi", + "section": "def-common.TaskPayloadPNGV2", + "text": "TaskPayloadPNGV2" + }, + ", cancellationToken: ", + { + "pluginId": "@kbn/reporting-common", + "scope": "common", + "docId": "kibKbnReportingCommonPluginApi", + "section": "def-common.CancellationToken", + "text": "CancellationToken" + }, + ", stream: ", + "Writable", + ") => Promise<", + "TaskRunResult", + ">" + ], + "path": "packages/kbn-reporting/export_types/png/png_v2.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/reporting-export-types-png", + "id": "def-server.PngExportType.runTask.$1", + "type": "string", + "tags": [], + "label": "jobId", + "description": [], + "signature": [ + "string" + ], + "path": "packages/kbn-reporting/export_types/png/png_v2.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/reporting-export-types-png", + "id": "def-server.PngExportType.runTask.$2", + "type": "Object", + "tags": [], + "label": "payload", + "description": [], + "signature": [ + { + "pluginId": "@kbn/reporting-export-types-png-common", + "scope": "common", + "docId": "kibKbnReportingExportTypesPngCommonPluginApi", + "section": "def-common.TaskPayloadPNGV2", + "text": "TaskPayloadPNGV2" + } + ], + "path": "packages/kbn-reporting/export_types/png/png_v2.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/reporting-export-types-png", + "id": "def-server.PngExportType.runTask.$3", + "type": "Object", + "tags": [], + "label": "cancellationToken", + "description": [], + "signature": [ + { + "pluginId": "@kbn/reporting-common", + "scope": "common", + "docId": "kibKbnReportingCommonPluginApi", + "section": "def-common.CancellationToken", + "text": "CancellationToken" + } + ], + "path": "packages/kbn-reporting/export_types/png/png_v2.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/reporting-export-types-png", + "id": "def-server.PngExportType.runTask.$4", + "type": "Object", + "tags": [], + "label": "stream", + "description": [], + "signature": [ + "Writable" + ], + "path": "packages/kbn-reporting/export_types/png/png_v2.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + } + ], + "initialIsOpen": false + } + ], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] + }, + "common": { + "classes": [], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] + } +} \ No newline at end of file diff --git a/api_docs/kbn_reporting_export_types_png.mdx b/api_docs/kbn_reporting_export_types_png.mdx new file mode 100644 index 0000000000000..086d6edf5d3a0 --- /dev/null +++ b/api_docs/kbn_reporting_export_types_png.mdx @@ -0,0 +1,30 @@ +--- +#### +#### 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: kibKbnReportingExportTypesPngPluginApi +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: 2023-11-16 +tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/reporting-export-types-png'] +--- +import kbnReportingExportTypesPngObj from './kbn_reporting_export_types_png.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 | +|-------------------|-----------|------------------------|-----------------| +| 16 | 0 | 15 | 0 | + +## Server + +### Classes + + diff --git a/api_docs/kbn_reporting_export_types_png_common.devdocs.json b/api_docs/kbn_reporting_export_types_png_common.devdocs.json new file mode 100644 index 0000000000000..01af24bb97bc6 --- /dev/null +++ b/api_docs/kbn_reporting_export_types_png_common.devdocs.json @@ -0,0 +1,280 @@ +{ + "id": "@kbn/reporting-export-types-png-common", + "client": { + "classes": [], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] + }, + "server": { + "classes": [], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] + }, + "common": { + "classes": [], + "functions": [], + "interfaces": [ + { + "parentPluginId": "@kbn/reporting-export-types-png-common", + "id": "def-common.JobParamsPNGV2", + "type": "Interface", + "tags": [], + "label": "JobParamsPNGV2", + "description": [], + "signature": [ + { + "pluginId": "@kbn/reporting-export-types-png-common", + "scope": "common", + "docId": "kibKbnReportingExportTypesPngCommonPluginApi", + "section": "def-common.JobParamsPNGV2", + "text": "JobParamsPNGV2" + }, + " extends ", + "BaseParams" + ], + "path": "packages/kbn-reporting/export_types/png_common/index.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/reporting-export-types-png-common", + "id": "def-common.JobParamsPNGV2.layout", + "type": "Object", + "tags": [], + "label": "layout", + "description": [], + "signature": [ + "{ id?: ", + { + "pluginId": "screenshotting", + "scope": "common", + "docId": "kibScreenshottingPluginApi", + "section": "def-common.LayoutType", + "text": "LayoutType" + }, + " | undefined; dimensions?: { width: number; height: number; } | undefined; selectors?: Partial<", + "LayoutSelectorDictionary", + "> | undefined; zoom?: number | undefined; }" + ], + "path": "packages/kbn-reporting/export_types/png_common/index.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/reporting-export-types-png-common", + "id": "def-common.JobParamsPNGV2.locatorParams", + "type": "Object", + "tags": [], + "label": "locatorParams", + "description": [ + "\nThis value is used to re-create the same visual state as when the report was requested as well as navigate to the correct page." + ], + "signature": [ + "LocatorParams", + "<", + { + "pluginId": "@kbn/utility-types", + "scope": "common", + "docId": "kibKbnUtilityTypesPluginApi", + "section": "def-common.SerializableRecord", + "text": "SerializableRecord" + }, + ">" + ], + "path": "packages/kbn-reporting/export_types/png_common/index.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/reporting-export-types-png-common", + "id": "def-common.TaskPayloadPNGV2", + "type": "Interface", + "tags": [], + "label": "TaskPayloadPNGV2", + "description": [], + "signature": [ + { + "pluginId": "@kbn/reporting-export-types-png-common", + "scope": "common", + "docId": "kibKbnReportingExportTypesPngCommonPluginApi", + "section": "def-common.TaskPayloadPNGV2", + "text": "TaskPayloadPNGV2" + }, + " extends ", + "BasePayload" + ], + "path": "packages/kbn-reporting/export_types/png_common/index.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/reporting-export-types-png-common", + "id": "def-common.TaskPayloadPNGV2.layout", + "type": "Object", + "tags": [], + "label": "layout", + "description": [], + "signature": [ + "{ id?: ", + { + "pluginId": "screenshotting", + "scope": "common", + "docId": "kibScreenshottingPluginApi", + "section": "def-common.LayoutType", + "text": "LayoutType" + }, + " | undefined; dimensions?: { width: number; height: number; } | undefined; selectors?: Partial<", + "LayoutSelectorDictionary", + "> | undefined; zoom?: number | undefined; }" + ], + "path": "packages/kbn-reporting/export_types/png_common/index.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/reporting-export-types-png-common", + "id": "def-common.TaskPayloadPNGV2.forceNow", + "type": "string", + "tags": [], + "label": "forceNow", + "description": [], + "path": "packages/kbn-reporting/export_types/png_common/index.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/reporting-export-types-png-common", + "id": "def-common.TaskPayloadPNGV2.locatorParams", + "type": "Array", + "tags": [], + "label": "locatorParams", + "description": [ + "\nEven though we only ever handle one locator for a PNG, we store it as an array for consistency with how PDFs are stored" + ], + "signature": [ + "LocatorParams", + "<", + { + "pluginId": "@kbn/utility-types", + "scope": "common", + "docId": "kibKbnUtilityTypesPluginApi", + "section": "def-common.SerializableRecord", + "text": "SerializableRecord" + }, + ">[]" + ], + "path": "packages/kbn-reporting/export_types/png_common/index.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + } + ], + "enums": [], + "misc": [ + { + "parentPluginId": "@kbn/reporting-export-types-png-common", + "id": "def-common.JobParamsPNGDeprecated", + "type": "Type", + "tags": [], + "label": "JobParamsPNGDeprecated", + "description": [], + "signature": [ + "BaseParamsPNG & ", + "BaseParams" + ], + "path": "packages/kbn-reporting/export_types/png_common/index.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/reporting-export-types-png-common", + "id": "def-common.PNG_JOB_TYPE", + "type": "string", + "tags": [], + "label": "PNG_JOB_TYPE", + "description": [], + "signature": [ + "\"PNG\"" + ], + "path": "packages/kbn-reporting/export_types/png_common/constants.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/reporting-export-types-png-common", + "id": "def-common.PNG_JOB_TYPE_V2", + "type": "string", + "tags": [], + "label": "PNG_JOB_TYPE_V2", + "description": [], + "signature": [ + "\"PNGV2\"" + ], + "path": "packages/kbn-reporting/export_types/png_common/constants.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/reporting-export-types-png-common", + "id": "def-common.PNG_REPORT_TYPE", + "type": "string", + "tags": [], + "label": "PNG_REPORT_TYPE", + "description": [], + "signature": [ + "\"PNG\"" + ], + "path": "packages/kbn-reporting/export_types/png_common/constants.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/reporting-export-types-png-common", + "id": "def-common.PNG_REPORT_TYPE_V2", + "type": "string", + "tags": [], + "label": "PNG_REPORT_TYPE_V2", + "description": [], + "signature": [ + "\"pngV2\"" + ], + "path": "packages/kbn-reporting/export_types/png_common/constants.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/reporting-export-types-png-common", + "id": "def-common.TaskPayloadPNG", + "type": "Type", + "tags": [], + "label": "TaskPayloadPNG", + "description": [], + "signature": [ + "BaseParamsPNG & ", + "BasePayload" + ], + "path": "packages/kbn-reporting/export_types/png_common/index.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + } + ], + "objects": [] + } +} \ No newline at end of file diff --git a/api_docs/kbn_reporting_export_types_png_common.mdx b/api_docs/kbn_reporting_export_types_png_common.mdx new file mode 100644 index 0000000000000..33f9aecbbc29b --- /dev/null +++ b/api_docs/kbn_reporting_export_types_png_common.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: kibKbnReportingExportTypesPngCommonPluginApi +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: 2023-11-16 +tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/reporting-export-types-png-common'] +--- +import kbnReportingExportTypesPngCommonObj from './kbn_reporting_export_types_png_common.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 | +|-------------------|-----------|------------------------|-----------------| +| 13 | 0 | 11 | 0 | + +## Common + +### Interfaces + + +### Consts, variables and types + + diff --git a/api_docs/kbn_reporting_mocks_server.devdocs.json b/api_docs/kbn_reporting_mocks_server.devdocs.json new file mode 100644 index 0000000000000..12ee6a35918a5 --- /dev/null +++ b/api_docs/kbn_reporting_mocks_server.devdocs.json @@ -0,0 +1,88 @@ +{ + "id": "@kbn/reporting-mocks-server", + "client": { + "classes": [], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] + }, + "server": { + "classes": [], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] + }, + "common": { + "classes": [], + "functions": [ + { + "parentPluginId": "@kbn/reporting-mocks-server", + "id": "def-common.createMockConfigSchema", + "type": "Function", + "tags": [], + "label": "createMockConfigSchema", + "description": [], + "signature": [ + "(overrides?: ", + "_DeepPartialObject", + "; kibanaServer: Readonly<{ hostname?: string | undefined; protocol?: string | undefined; port?: number | undefined; } & {}>; queue: Readonly<{} & { timeout: number | moment.Duration; pollInterval: number | moment.Duration; indexInterval: string; pollEnabled: boolean; pollIntervalErrorMultiplier: number; }>; csv: Readonly<{} & { scroll: Readonly<{} & { duration: string; size: number; }>; checkForFormulas: boolean; escapeFormulaValues: boolean; enablePanelActionDownload: boolean; maxSizeBytes: number | ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ByteSizeValue", + "text": "ByteSizeValue" + }, + "; useByteOrderMarkEncoding: boolean; }>; roles: Readonly<{} & { enabled: boolean; allow: string[]; }>; poll: Readonly<{} & { jobCompletionNotifier: Readonly<{} & { interval: number; intervalErrorMultiplier: number; }>; jobsRefresh: Readonly<{} & { interval: number; intervalErrorMultiplier: number; }>; }>; export_types: Readonly<{} & { csv: Readonly<{} & { enabled: boolean; }>; png: Readonly<{} & { enabled: boolean; }>; pdf: Readonly<{} & { enabled: boolean; }>; }>; statefulSettings: Readonly<{} & { enabled: boolean; }>; }>>) => Readonly<{ encryptionKey?: string | undefined; } & { enabled: boolean; capture: Readonly<{} & { maxAttempts: number; }>; kibanaServer: Readonly<{ hostname?: string | undefined; protocol?: string | undefined; port?: number | undefined; } & {}>; queue: Readonly<{} & { timeout: number | moment.Duration; pollInterval: number | moment.Duration; indexInterval: string; pollEnabled: boolean; pollIntervalErrorMultiplier: number; }>; csv: Readonly<{} & { scroll: Readonly<{} & { duration: string; size: number; }>; checkForFormulas: boolean; escapeFormulaValues: boolean; enablePanelActionDownload: boolean; maxSizeBytes: number | ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ByteSizeValue", + "text": "ByteSizeValue" + }, + "; useByteOrderMarkEncoding: boolean; }>; roles: Readonly<{} & { enabled: boolean; allow: string[]; }>; poll: Readonly<{} & { jobCompletionNotifier: Readonly<{} & { interval: number; intervalErrorMultiplier: number; }>; jobsRefresh: Readonly<{} & { interval: number; intervalErrorMultiplier: number; }>; }>; export_types: Readonly<{} & { csv: Readonly<{} & { enabled: boolean; }>; png: Readonly<{} & { enabled: boolean; }>; pdf: Readonly<{} & { enabled: boolean; }>; }>; statefulSettings: Readonly<{} & { enabled: boolean; }>; }>" + ], + "path": "packages/kbn-reporting/mocks_server/index.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/reporting-mocks-server", + "id": "def-common.createMockConfigSchema.$1", + "type": "Object", + "tags": [], + "label": "overrides", + "description": [], + "signature": [ + "_DeepPartialObject", + "; kibanaServer: Readonly<{ hostname?: string | undefined; protocol?: string | undefined; port?: number | undefined; } & {}>; queue: Readonly<{} & { timeout: number | moment.Duration; pollInterval: number | moment.Duration; indexInterval: string; pollEnabled: boolean; pollIntervalErrorMultiplier: number; }>; csv: Readonly<{} & { scroll: Readonly<{} & { duration: string; size: number; }>; checkForFormulas: boolean; escapeFormulaValues: boolean; enablePanelActionDownload: boolean; maxSizeBytes: number | ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ByteSizeValue", + "text": "ByteSizeValue" + }, + "; useByteOrderMarkEncoding: boolean; }>; roles: Readonly<{} & { enabled: boolean; allow: string[]; }>; poll: Readonly<{} & { jobCompletionNotifier: Readonly<{} & { interval: number; intervalErrorMultiplier: number; }>; jobsRefresh: Readonly<{} & { interval: number; intervalErrorMultiplier: number; }>; }>; export_types: Readonly<{} & { csv: Readonly<{} & { enabled: boolean; }>; png: Readonly<{} & { enabled: boolean; }>; pdf: Readonly<{} & { enabled: boolean; }>; }>; statefulSettings: Readonly<{} & { enabled: boolean; }>; }>>" + ], + "path": "packages/kbn-reporting/mocks_server/index.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [], + "initialIsOpen": false + } + ], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] + } +} \ No newline at end of file diff --git a/api_docs/kbn_reporting_mocks_server.mdx b/api_docs/kbn_reporting_mocks_server.mdx new file mode 100644 index 0000000000000..c67ab41fcf43d --- /dev/null +++ b/api_docs/kbn_reporting_mocks_server.mdx @@ -0,0 +1,30 @@ +--- +#### +#### 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: kibKbnReportingMocksServerPluginApi +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: 2023-11-16 +tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/reporting-mocks-server'] +--- +import kbnReportingMocksServerObj from './kbn_reporting_mocks_server.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 | +|-------------------|-----------|------------------------|-----------------| +| 2 | 0 | 2 | 0 | + +## Common + +### Functions + + diff --git a/api_docs/kbn_reporting_public.devdocs.json b/api_docs/kbn_reporting_public.devdocs.json new file mode 100644 index 0000000000000..5acb381f4e2a3 --- /dev/null +++ b/api_docs/kbn_reporting_public.devdocs.json @@ -0,0 +1,98 @@ +{ + "id": "@kbn/reporting-public", + "client": { + "classes": [], + "functions": [], + "interfaces": [ + { + "parentPluginId": "@kbn/reporting-public", + "id": "def-public.ClientConfigType", + "type": "Interface", + "tags": [], + "label": "ClientConfigType", + "description": [], + "path": "packages/kbn-reporting/public/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/reporting-public", + "id": "def-public.ClientConfigType.poll", + "type": "Object", + "tags": [], + "label": "poll", + "description": [], + "signature": [ + "{ jobsRefresh: { interval: number; intervalErrorMultiplier: number; }; }" + ], + "path": "packages/kbn-reporting/public/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/reporting-public", + "id": "def-public.ClientConfigType.roles", + "type": "Object", + "tags": [], + "label": "roles", + "description": [], + "signature": [ + "{ enabled: boolean; }" + ], + "path": "packages/kbn-reporting/public/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/reporting-public", + "id": "def-public.ClientConfigType.export_types", + "type": "Object", + "tags": [], + "label": "export_types", + "description": [], + "signature": [ + "{ pdf: { enabled: boolean; }; png: { enabled: boolean; }; csv: { enabled: boolean; }; }" + ], + "path": "packages/kbn-reporting/public/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/reporting-public", + "id": "def-public.ClientConfigType.statefulSettings", + "type": "Object", + "tags": [], + "label": "statefulSettings", + "description": [], + "signature": [ + "{ enabled: boolean; }" + ], + "path": "packages/kbn-reporting/public/types.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + } + ], + "enums": [], + "misc": [], + "objects": [] + }, + "server": { + "classes": [], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] + }, + "common": { + "classes": [], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] + } +} \ No newline at end of file diff --git a/api_docs/kbn_generate_csv_types.mdx b/api_docs/kbn_reporting_public.mdx similarity index 55% rename from api_docs/kbn_generate_csv_types.mdx rename to api_docs/kbn_reporting_public.mdx index 0a73097004a56..6861b7b789720 100644 --- a/api_docs/kbn_generate_csv_types.mdx +++ b/api_docs/kbn_reporting_public.mdx @@ -3,15 +3,15 @@ #### 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: kibKbnGenerateCsvTypesPluginApi -slug: /kibana-dev-docs/api/kbn-generate-csv-types -title: "@kbn/generate-csv-types" +id: kibKbnReportingPublicPluginApi +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/generate-csv-types plugin -date: 2023-11-14 -tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/generate-csv-types'] +description: API docs for the @kbn/reporting-public plugin +date: 2023-11-16 +tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/reporting-public'] --- -import kbnGenerateCsvTypesObj from './kbn_generate_csv_types.devdocs.json'; +import kbnReportingPublicObj from './kbn_reporting_public.devdocs.json'; @@ -21,10 +21,10 @@ Contact [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sh | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 10 | 0 | 10 | 0 | +| 5 | 0 | 5 | 0 | -## Common +## Client ### Interfaces - + diff --git a/api_docs/kbn_reporting_server.devdocs.json b/api_docs/kbn_reporting_server.devdocs.json new file mode 100644 index 0000000000000..f2c2ef84cfa8c --- /dev/null +++ b/api_docs/kbn_reporting_server.devdocs.json @@ -0,0 +1,1972 @@ +{ + "id": "@kbn/reporting-server", + "client": { + "classes": [], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] + }, + "server": { + "classes": [ + { + "parentPluginId": "@kbn/reporting-server", + "id": "def-server.ExportType", + "type": "Class", + "tags": [], + "label": "ExportType", + "description": [], + "signature": [ + { + "pluginId": "@kbn/reporting-server", + "scope": "server", + "docId": "kibKbnReportingServerPluginApi", + "section": "def-server.ExportType", + "text": "ExportType" + }, + "" + ], + "path": "packages/kbn-reporting/server/export_type.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/reporting-server", + "id": "def-server.ExportType.id", + "type": "string", + "tags": [], + "label": "id", + "description": [], + "path": "packages/kbn-reporting/server/export_type.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/reporting-server", + "id": "def-server.ExportType.name", + "type": "string", + "tags": [], + "label": "name", + "description": [], + "path": "packages/kbn-reporting/server/export_type.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/reporting-server", + "id": "def-server.ExportType.jobType", + "type": "string", + "tags": [], + "label": "jobType", + "description": [], + "path": "packages/kbn-reporting/server/export_type.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/reporting-server", + "id": "def-server.ExportType.jobContentEncoding", + "type": "CompoundType", + "tags": [], + "label": "jobContentEncoding", + "description": [], + "signature": [ + "\"base64\" | \"csv\" | undefined" + ], + "path": "packages/kbn-reporting/server/export_type.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/reporting-server", + "id": "def-server.ExportType.jobContentExtension", + "type": "CompoundType", + "tags": [], + "label": "jobContentExtension", + "description": [], + "signature": [ + "\"csv\" | \"png\" | \"pdf\"" + ], + "path": "packages/kbn-reporting/server/export_type.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/reporting-server", + "id": "def-server.ExportType.createJob", + "type": "Function", + "tags": [], + "label": "createJob", + "description": [], + "signature": [ + "(jobParams: JobParamsType, context: ", + { + "pluginId": "@kbn/core-http-request-handler-context-server", + "scope": "common", + "docId": "kibKbnCoreHttpRequestHandlerContextServerPluginApi", + "section": "def-common.CustomRequestHandlerContext", + "text": "CustomRequestHandlerContext" + }, + "<{ reporting: ", + { + "pluginId": "@kbn/reporting-server", + "scope": "server", + "docId": "kibKbnReportingServerPluginApi", + "section": "def-server.ReportingServerPluginSetup", + "text": "ReportingServerPluginSetup" + }, + " | null; }>, req: ", + { + "pluginId": "@kbn/core-http-server", + "scope": "common", + "docId": "kibKbnCoreHttpServerPluginApi", + "section": "def-common.KibanaRequest", + "text": "KibanaRequest" + }, + ") => Promise>" + ], + "path": "packages/kbn-reporting/server/export_type.ts", + "deprecated": false, + "trackAdoption": false, + "returnComment": [], + "children": [ + { + "parentPluginId": "@kbn/reporting-server", + "id": "def-server.ExportType.createJob.$1", + "type": "Uncategorized", + "tags": [], + "label": "jobParams", + "description": [], + "signature": [ + "JobParamsType" + ], + "path": "packages/kbn-reporting/server/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/reporting-server", + "id": "def-server.ExportType.createJob.$2", + "type": "CompoundType", + "tags": [], + "label": "context", + "description": [], + "signature": [ + { + "pluginId": "@kbn/core-http-request-handler-context-server", + "scope": "common", + "docId": "kibKbnCoreHttpRequestHandlerContextServerPluginApi", + "section": "def-common.RequestHandlerContext", + "text": "RequestHandlerContext" + }, + " & { reporting: Promise<", + { + "pluginId": "@kbn/reporting-server", + "scope": "server", + "docId": "kibKbnReportingServerPluginApi", + "section": "def-server.ReportingServerPluginSetup", + "text": "ReportingServerPluginSetup" + }, + " | null>; }" + ], + "path": "packages/kbn-reporting/server/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/reporting-server", + "id": "def-server.ExportType.createJob.$3", + "type": "Object", + "tags": [], + "label": "req", + "description": [], + "signature": [ + { + "pluginId": "@kbn/core-http-server", + "scope": "common", + "docId": "kibKbnCoreHttpServerPluginApi", + "section": "def-common.KibanaRequest", + "text": "KibanaRequest" + }, + "" + ], + "path": "packages/kbn-reporting/server/types.ts", + "deprecated": false, + "trackAdoption": false + } + ] + }, + { + "parentPluginId": "@kbn/reporting-server", + "id": "def-server.ExportType.runTask", + "type": "Function", + "tags": [], + "label": "runTask", + "description": [], + "signature": [ + "(jobId: string, payload: TaskPayloadType, cancellationToken: ", + { + "pluginId": "@kbn/reporting-common", + "scope": "common", + "docId": "kibKbnReportingCommonPluginApi", + "section": "def-common.CancellationToken", + "text": "CancellationToken" + }, + ", stream: ", + "Writable", + ") => Promise<", + "TaskRunResult", + ">" + ], + "path": "packages/kbn-reporting/server/export_type.ts", + "deprecated": false, + "trackAdoption": false, + "returnComment": [], + "children": [ + { + "parentPluginId": "@kbn/reporting-server", + "id": "def-server.ExportType.runTask.$1", + "type": "string", + "tags": [], + "label": "jobId", + "description": [], + "path": "packages/kbn-reporting/server/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/reporting-server", + "id": "def-server.ExportType.runTask.$2", + "type": "Uncategorized", + "tags": [], + "label": "payload", + "description": [], + "signature": [ + "TaskPayloadType" + ], + "path": "packages/kbn-reporting/server/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/reporting-server", + "id": "def-server.ExportType.runTask.$3", + "type": "Object", + "tags": [], + "label": "cancellationToken", + "description": [], + "signature": [ + { + "pluginId": "@kbn/reporting-common", + "scope": "common", + "docId": "kibKbnReportingCommonPluginApi", + "section": "def-common.CancellationToken", + "text": "CancellationToken" + } + ], + "path": "packages/kbn-reporting/server/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/reporting-server", + "id": "def-server.ExportType.runTask.$4", + "type": "Object", + "tags": [], + "label": "stream", + "description": [], + "signature": [ + "Writable" + ], + "path": "packages/kbn-reporting/server/types.ts", + "deprecated": false, + "trackAdoption": false + } + ] + }, + { + "parentPluginId": "@kbn/reporting-server", + "id": "def-server.ExportType.validLicenses", + "type": "Array", + "tags": [], + "label": "validLicenses", + "description": [], + "signature": [ + "(\"basic\" | \"standard\" | \"gold\" | \"platinum\" | \"enterprise\" | \"trial\")[]" + ], + "path": "packages/kbn-reporting/server/export_type.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/reporting-server", + "id": "def-server.ExportType.setupDeps", + "type": "Uncategorized", + "tags": [], + "label": "setupDeps", + "description": [], + "signature": [ + "SetupDepsType" + ], + "path": "packages/kbn-reporting/server/export_type.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/reporting-server", + "id": "def-server.ExportType.startDeps", + "type": "Uncategorized", + "tags": [], + "label": "startDeps", + "description": [], + "signature": [ + "StartDepsType" + ], + "path": "packages/kbn-reporting/server/export_type.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/reporting-server", + "id": "def-server.ExportType.http", + "type": "Object", + "tags": [], + "label": "http", + "description": [], + "signature": [ + { + "pluginId": "@kbn/core-http-server", + "scope": "common", + "docId": "kibKbnCoreHttpServerPluginApi", + "section": "def-common.HttpServiceSetup", + "text": "HttpServiceSetup" + }, + "<", + { + "pluginId": "@kbn/core-http-server", + "scope": "common", + "docId": "kibKbnCoreHttpServerPluginApi", + "section": "def-common.RequestHandlerContextBase", + "text": "RequestHandlerContextBase" + }, + ">" + ], + "path": "packages/kbn-reporting/server/export_type.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/reporting-server", + "id": "def-server.ExportType.Unnamed", + "type": "Function", + "tags": [], + "label": "Constructor", + "description": [], + "signature": [ + "any" + ], + "path": "packages/kbn-reporting/server/export_type.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/reporting-server", + "id": "def-server.ExportType.Unnamed.$1", + "type": "Object", + "tags": [], + "label": "core", + "description": [], + "signature": [ + { + "pluginId": "@kbn/core-lifecycle-server", + "scope": "common", + "docId": "kibKbnCoreLifecycleServerPluginApi", + "section": "def-common.CoreSetup", + "text": "CoreSetup" + }, + "" + ], + "path": "packages/kbn-reporting/server/export_type.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/reporting-server", + "id": "def-server.ExportType.Unnamed.$2", + "type": "Object", + "tags": [], + "label": "config", + "description": [], + "signature": [ + "Readonly<{ encryptionKey?: string | undefined; } & { enabled: boolean; capture: Readonly<{} & { maxAttempts: number; }>; kibanaServer: Readonly<{ hostname?: string | undefined; protocol?: string | undefined; port?: number | undefined; } & {}>; queue: Readonly<{} & { timeout: number | moment.Duration; pollInterval: number | moment.Duration; indexInterval: string; pollEnabled: boolean; pollIntervalErrorMultiplier: number; }>; csv: Readonly<{} & { scroll: Readonly<{} & { duration: string; size: number; }>; checkForFormulas: boolean; escapeFormulaValues: boolean; enablePanelActionDownload: boolean; maxSizeBytes: number | ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ByteSizeValue", + "text": "ByteSizeValue" + }, + "; useByteOrderMarkEncoding: boolean; }>; roles: Readonly<{} & { enabled: boolean; allow: string[]; }>; poll: Readonly<{} & { jobCompletionNotifier: Readonly<{} & { interval: number; intervalErrorMultiplier: number; }>; jobsRefresh: Readonly<{} & { interval: number; intervalErrorMultiplier: number; }>; }>; export_types: Readonly<{} & { csv: Readonly<{} & { enabled: boolean; }>; png: Readonly<{} & { enabled: boolean; }>; pdf: Readonly<{} & { enabled: boolean; }>; }>; statefulSettings: Readonly<{} & { enabled: boolean; }>; }>" + ], + "path": "packages/kbn-reporting/server/export_type.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/reporting-server", + "id": "def-server.ExportType.Unnamed.$3", + "type": "Object", + "tags": [], + "label": "logger", + "description": [], + "signature": [ + { + "pluginId": "@kbn/logging", + "scope": "common", + "docId": "kibKbnLoggingPluginApi", + "section": "def-common.Logger", + "text": "Logger" + } + ], + "path": "packages/kbn-reporting/server/export_type.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/reporting-server", + "id": "def-server.ExportType.Unnamed.$4", + "type": "Object", + "tags": [], + "label": "context", + "description": [], + "signature": [ + { + "pluginId": "@kbn/core-plugins-server", + "scope": "common", + "docId": "kibKbnCorePluginsServerPluginApi", + "section": "def-common.PluginInitializerContext", + "text": "PluginInitializerContext" + }, + "; kibanaServer: Readonly<{ hostname?: string | undefined; protocol?: string | undefined; port?: number | undefined; } & {}>; queue: Readonly<{} & { timeout: number | moment.Duration; pollInterval: number | moment.Duration; indexInterval: string; pollEnabled: boolean; pollIntervalErrorMultiplier: number; }>; csv: Readonly<{} & { scroll: Readonly<{} & { duration: string; size: number; }>; checkForFormulas: boolean; escapeFormulaValues: boolean; enablePanelActionDownload: boolean; maxSizeBytes: number | ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ByteSizeValue", + "text": "ByteSizeValue" + }, + "; useByteOrderMarkEncoding: boolean; }>; roles: Readonly<{} & { enabled: boolean; allow: string[]; }>; poll: Readonly<{} & { jobCompletionNotifier: Readonly<{} & { interval: number; intervalErrorMultiplier: number; }>; jobsRefresh: Readonly<{} & { interval: number; intervalErrorMultiplier: number; }>; }>; export_types: Readonly<{} & { csv: Readonly<{} & { enabled: boolean; }>; png: Readonly<{} & { enabled: boolean; }>; pdf: Readonly<{} & { enabled: boolean; }>; }>; statefulSettings: Readonly<{} & { enabled: boolean; }>; }>>" + ], + "path": "packages/kbn-reporting/server/export_type.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/reporting-server", + "id": "def-server.ExportType.setup", + "type": "Function", + "tags": [], + "label": "setup", + "description": [], + "signature": [ + "(setupDeps: SetupDepsType) => void" + ], + "path": "packages/kbn-reporting/server/export_type.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/reporting-server", + "id": "def-server.ExportType.setup.$1", + "type": "Uncategorized", + "tags": [], + "label": "setupDeps", + "description": [], + "signature": [ + "SetupDepsType" + ], + "path": "packages/kbn-reporting/server/export_type.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/reporting-server", + "id": "def-server.ExportType.start", + "type": "Function", + "tags": [], + "label": "start", + "description": [], + "signature": [ + "(startDeps: StartDepsType) => void" + ], + "path": "packages/kbn-reporting/server/export_type.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/reporting-server", + "id": "def-server.ExportType.start.$1", + "type": "Uncategorized", + "tags": [], + "label": "startDeps", + "description": [], + "signature": [ + "StartDepsType" + ], + "path": "packages/kbn-reporting/server/export_type.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/reporting-server", + "id": "def-server.ExportType.getUiSettingsServiceFactory", + "type": "Function", + "tags": [], + "label": "getUiSettingsServiceFactory", + "description": [], + "signature": [ + "(savedObjectsClient: ", + { + "pluginId": "@kbn/core-saved-objects-api-server", + "scope": "common", + "docId": "kibKbnCoreSavedObjectsApiServerPluginApi", + "section": "def-common.SavedObjectsClientContract", + "text": "SavedObjectsClientContract" + }, + ") => ", + { + "pluginId": "@kbn/core-ui-settings-server", + "scope": "common", + "docId": "kibKbnCoreUiSettingsServerPluginApi", + "section": "def-common.IUiSettingsClient", + "text": "IUiSettingsClient" + } + ], + "path": "packages/kbn-reporting/server/export_type.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/reporting-server", + "id": "def-server.ExportType.getUiSettingsServiceFactory.$1", + "type": "Object", + "tags": [], + "label": "savedObjectsClient", + "description": [], + "signature": [ + { + "pluginId": "@kbn/core-saved-objects-api-server", + "scope": "common", + "docId": "kibKbnCoreSavedObjectsApiServerPluginApi", + "section": "def-common.SavedObjectsClientContract", + "text": "SavedObjectsClientContract" + } + ], + "path": "packages/kbn-reporting/server/export_type.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/reporting-server", + "id": "def-server.ExportType.getUiSettingsClient", + "type": "Function", + "tags": [], + "label": "getUiSettingsClient", + "description": [], + "signature": [ + "(request: ", + { + "pluginId": "@kbn/core-http-server", + "scope": "common", + "docId": "kibKbnCoreHttpServerPluginApi", + "section": "def-common.KibanaRequest", + "text": "KibanaRequest" + }, + ", logger?: ", + { + "pluginId": "@kbn/logging", + "scope": "common", + "docId": "kibKbnLoggingPluginApi", + "section": "def-common.Logger", + "text": "Logger" + }, + ") => Promise<", + { + "pluginId": "@kbn/core-ui-settings-server", + "scope": "common", + "docId": "kibKbnCoreUiSettingsServerPluginApi", + "section": "def-common.IUiSettingsClient", + "text": "IUiSettingsClient" + }, + ">" + ], + "path": "packages/kbn-reporting/server/export_type.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/reporting-server", + "id": "def-server.ExportType.getUiSettingsClient.$1", + "type": "Object", + "tags": [], + "label": "request", + "description": [], + "signature": [ + { + "pluginId": "@kbn/core-http-server", + "scope": "common", + "docId": "kibKbnCoreHttpServerPluginApi", + "section": "def-common.KibanaRequest", + "text": "KibanaRequest" + }, + "" + ], + "path": "packages/kbn-reporting/server/export_type.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/reporting-server", + "id": "def-server.ExportType.getUiSettingsClient.$2", + "type": "Object", + "tags": [], + "label": "logger", + "description": [], + "signature": [ + { + "pluginId": "@kbn/logging", + "scope": "common", + "docId": "kibKbnLoggingPluginApi", + "section": "def-common.Logger", + "text": "Logger" + } + ], + "path": "packages/kbn-reporting/server/export_type.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/reporting-server", + "id": "def-server.ExportType.getFakeRequest", + "type": "Function", + "tags": [], + "label": "getFakeRequest", + "description": [], + "signature": [ + "(headers: ", + { + "pluginId": "@kbn/core-http-server", + "scope": "common", + "docId": "kibKbnCoreHttpServerPluginApi", + "section": "def-common.Headers", + "text": "Headers" + }, + ", spaceId: string | undefined, logger?: ", + { + "pluginId": "@kbn/logging", + "scope": "common", + "docId": "kibKbnLoggingPluginApi", + "section": "def-common.Logger", + "text": "Logger" + }, + ") => ", + { + "pluginId": "@kbn/core-http-server", + "scope": "common", + "docId": "kibKbnCoreHttpServerPluginApi", + "section": "def-common.KibanaRequest", + "text": "KibanaRequest" + }, + "" + ], + "path": "packages/kbn-reporting/server/export_type.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/reporting-server", + "id": "def-server.ExportType.getFakeRequest.$1", + "type": "CompoundType", + "tags": [], + "label": "headers", + "description": [], + "signature": [ + { + "pluginId": "@kbn/core-http-server", + "scope": "common", + "docId": "kibKbnCoreHttpServerPluginApi", + "section": "def-common.Headers", + "text": "Headers" + } + ], + "path": "packages/kbn-reporting/server/export_type.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/reporting-server", + "id": "def-server.ExportType.getFakeRequest.$2", + "type": "string", + "tags": [], + "label": "spaceId", + "description": [], + "signature": [ + "string | undefined" + ], + "path": "packages/kbn-reporting/server/export_type.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": false + }, + { + "parentPluginId": "@kbn/reporting-server", + "id": "def-server.ExportType.getFakeRequest.$3", + "type": "Object", + "tags": [], + "label": "logger", + "description": [], + "signature": [ + { + "pluginId": "@kbn/logging", + "scope": "common", + "docId": "kibKbnLoggingPluginApi", + "section": "def-common.Logger", + "text": "Logger" + } + ], + "path": "packages/kbn-reporting/server/export_type.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/reporting-server", + "id": "def-server.ExportType.getServerInfo", + "type": "Function", + "tags": [], + "label": "getServerInfo", + "description": [], + "signature": [ + "() => ", + "ReportingServerInfo" + ], + "path": "packages/kbn-reporting/server/export_type.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [] + } + ], + "initialIsOpen": false + } + ], + "functions": [ + { + "parentPluginId": "@kbn/reporting-server", + "id": "def-server.cryptoFactory", + "type": "Function", + "tags": [], + "label": "cryptoFactory", + "description": [], + "signature": [ + "(encryptionKey: string | undefined) => ", + "Crypto" + ], + "path": "packages/kbn-reporting/server/crypto.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/reporting-server", + "id": "def-server.cryptoFactory.$1", + "type": "string", + "tags": [], + "label": "encryptionKey", + "description": [], + "signature": [ + "string | undefined" + ], + "path": "packages/kbn-reporting/server/crypto.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": false + } + ], + "returnComment": [], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/reporting-server", + "id": "def-server.decryptJobHeaders", + "type": "Function", + "tags": [], + "label": "decryptJobHeaders", + "description": [], + "signature": [ + "(encryptionKey: string | undefined, headers: string, logger: ", + { + "pluginId": "@kbn/logging", + "scope": "common", + "docId": "kibKbnLoggingPluginApi", + "section": "def-common.Logger", + "text": "Logger" + }, + ") => Promise>" + ], + "path": "packages/kbn-reporting/server/decrypt_job_headers.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/reporting-server", + "id": "def-server.decryptJobHeaders.$1", + "type": "string", + "tags": [], + "label": "encryptionKey", + "description": [], + "signature": [ + "string | undefined" + ], + "path": "packages/kbn-reporting/server/decrypt_job_headers.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": false + }, + { + "parentPluginId": "@kbn/reporting-server", + "id": "def-server.decryptJobHeaders.$2", + "type": "string", + "tags": [], + "label": "headers", + "description": [], + "signature": [ + "string" + ], + "path": "packages/kbn-reporting/server/decrypt_job_headers.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/reporting-server", + "id": "def-server.decryptJobHeaders.$3", + "type": "Object", + "tags": [], + "label": "logger", + "description": [], + "signature": [ + { + "pluginId": "@kbn/logging", + "scope": "common", + "docId": "kibKbnLoggingPluginApi", + "section": "def-common.Logger", + "text": "Logger" + } + ], + "path": "packages/kbn-reporting/server/decrypt_job_headers.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/reporting-server", + "id": "def-server.getFieldFormats", + "type": "Function", + "tags": [], + "label": "getFieldFormats", + "description": [], + "signature": [ + "() => ", + { + "pluginId": "fieldFormats", + "scope": "server", + "docId": "kibFieldFormatsPluginApi", + "section": "def-server.FieldFormatsStart", + "text": "FieldFormatsStart" + } + ], + "path": "packages/kbn-reporting/server/services.ts", + "deprecated": false, + "trackAdoption": false, + "returnComment": [], + "children": [], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/reporting-server", + "id": "def-server.getFullRedirectAppUrl", + "type": "Function", + "tags": [], + "label": "getFullRedirectAppUrl", + "description": [], + "signature": [ + "(config: Readonly<{ encryptionKey?: string | undefined; } & { enabled: boolean; capture: Readonly<{} & { maxAttempts: number; }>; kibanaServer: Readonly<{ hostname?: string | undefined; protocol?: string | undefined; port?: number | undefined; } & {}>; queue: Readonly<{} & { timeout: number | moment.Duration; pollInterval: number | moment.Duration; indexInterval: string; pollEnabled: boolean; pollIntervalErrorMultiplier: number; }>; csv: Readonly<{} & { scroll: Readonly<{} & { duration: string; size: number; }>; checkForFormulas: boolean; escapeFormulaValues: boolean; enablePanelActionDownload: boolean; maxSizeBytes: number | ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ByteSizeValue", + "text": "ByteSizeValue" + }, + "; useByteOrderMarkEncoding: boolean; }>; roles: Readonly<{} & { enabled: boolean; allow: string[]; }>; poll: Readonly<{} & { jobCompletionNotifier: Readonly<{} & { interval: number; intervalErrorMultiplier: number; }>; jobsRefresh: Readonly<{} & { interval: number; intervalErrorMultiplier: number; }>; }>; export_types: Readonly<{} & { csv: Readonly<{} & { enabled: boolean; }>; png: Readonly<{} & { enabled: boolean; }>; pdf: Readonly<{} & { enabled: boolean; }>; }>; statefulSettings: Readonly<{} & { enabled: boolean; }>; }>, serverInfo: ", + "ReportingServerInfo", + ", spaceId: string | undefined, forceNow: string | undefined) => string" + ], + "path": "packages/kbn-reporting/server/get_full_redirect_app_url.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/reporting-server", + "id": "def-server.getFullRedirectAppUrl.$1", + "type": "Object", + "tags": [], + "label": "config", + "description": [], + "signature": [ + "Readonly<{ encryptionKey?: string | undefined; } & { enabled: boolean; capture: Readonly<{} & { maxAttempts: number; }>; kibanaServer: Readonly<{ hostname?: string | undefined; protocol?: string | undefined; port?: number | undefined; } & {}>; queue: Readonly<{} & { timeout: number | moment.Duration; pollInterval: number | moment.Duration; indexInterval: string; pollEnabled: boolean; pollIntervalErrorMultiplier: number; }>; csv: Readonly<{} & { scroll: Readonly<{} & { duration: string; size: number; }>; checkForFormulas: boolean; escapeFormulaValues: boolean; enablePanelActionDownload: boolean; maxSizeBytes: number | ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ByteSizeValue", + "text": "ByteSizeValue" + }, + "; useByteOrderMarkEncoding: boolean; }>; roles: Readonly<{} & { enabled: boolean; allow: string[]; }>; poll: Readonly<{} & { jobCompletionNotifier: Readonly<{} & { interval: number; intervalErrorMultiplier: number; }>; jobsRefresh: Readonly<{} & { interval: number; intervalErrorMultiplier: number; }>; }>; export_types: Readonly<{} & { csv: Readonly<{} & { enabled: boolean; }>; png: Readonly<{} & { enabled: boolean; }>; pdf: Readonly<{} & { enabled: boolean; }>; }>; statefulSettings: Readonly<{} & { enabled: boolean; }>; }>" + ], + "path": "packages/kbn-reporting/server/get_full_redirect_app_url.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/reporting-server", + "id": "def-server.getFullRedirectAppUrl.$2", + "type": "Object", + "tags": [], + "label": "serverInfo", + "description": [], + "signature": [ + "ReportingServerInfo" + ], + "path": "packages/kbn-reporting/server/get_full_redirect_app_url.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/reporting-server", + "id": "def-server.getFullRedirectAppUrl.$3", + "type": "string", + "tags": [], + "label": "spaceId", + "description": [], + "signature": [ + "string | undefined" + ], + "path": "packages/kbn-reporting/server/get_full_redirect_app_url.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": false + }, + { + "parentPluginId": "@kbn/reporting-server", + "id": "def-server.getFullRedirectAppUrl.$4", + "type": "string", + "tags": [], + "label": "forceNow", + "description": [], + "signature": [ + "string | undefined" + ], + "path": "packages/kbn-reporting/server/get_full_redirect_app_url.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": false + } + ], + "returnComment": [], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/reporting-server", + "id": "def-server.setFieldFormats", + "type": "Function", + "tags": [], + "label": "setFieldFormats", + "description": [], + "signature": [ + "(value: ", + { + "pluginId": "fieldFormats", + "scope": "server", + "docId": "kibFieldFormatsPluginApi", + "section": "def-server.FieldFormatsStart", + "text": "FieldFormatsStart" + }, + ") => void" + ], + "path": "packages/kbn-reporting/server/services.ts", + "deprecated": false, + "trackAdoption": false, + "returnComment": [], + "children": [ + { + "parentPluginId": "@kbn/reporting-server", + "id": "def-server.setFieldFormats.$1", + "type": "Uncategorized", + "tags": [], + "label": "value", + "description": [], + "signature": [ + "T" + ], + "path": "src/plugins/kibana_utils/common/create_getter_setter.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + } + ], + "interfaces": [ + { + "parentPluginId": "@kbn/reporting-server", + "id": "def-server.BaseExportTypeSetupDeps", + "type": "Interface", + "tags": [], + "label": "BaseExportTypeSetupDeps", + "description": [], + "path": "packages/kbn-reporting/server/export_type.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/reporting-server", + "id": "def-server.BaseExportTypeSetupDeps.basePath", + "type": "Object", + "tags": [], + "label": "basePath", + "description": [], + "signature": [ + "{ set: (request: ", + { + "pluginId": "@kbn/core-http-server", + "scope": "common", + "docId": "kibKbnCoreHttpServerPluginApi", + "section": "def-common.KibanaRequest", + "text": "KibanaRequest" + }, + ", requestSpecificBasePath: string) => void; }" + ], + "path": "packages/kbn-reporting/server/export_type.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/reporting-server", + "id": "def-server.BaseExportTypeSetupDeps.spaces", + "type": "Object", + "tags": [], + "label": "spaces", + "description": [], + "signature": [ + { + "pluginId": "spaces", + "scope": "server", + "docId": "kibSpacesPluginApi", + "section": "def-server.SpacesPluginSetup", + "text": "SpacesPluginSetup" + }, + " | undefined" + ], + "path": "packages/kbn-reporting/server/export_type.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/reporting-server", + "id": "def-server.BaseExportTypeStartDeps", + "type": "Interface", + "tags": [], + "label": "BaseExportTypeStartDeps", + "description": [], + "path": "packages/kbn-reporting/server/export_type.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/reporting-server", + "id": "def-server.BaseExportTypeStartDeps.savedObjects", + "type": "Object", + "tags": [], + "label": "savedObjects", + "description": [], + "signature": [ + { + "pluginId": "@kbn/core-saved-objects-server", + "scope": "common", + "docId": "kibKbnCoreSavedObjectsServerPluginApi", + "section": "def-common.SavedObjectsServiceStart", + "text": "SavedObjectsServiceStart" + } + ], + "path": "packages/kbn-reporting/server/export_type.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/reporting-server", + "id": "def-server.BaseExportTypeStartDeps.uiSettings", + "type": "Object", + "tags": [], + "label": "uiSettings", + "description": [], + "signature": [ + { + "pluginId": "@kbn/core-ui-settings-server", + "scope": "common", + "docId": "kibKbnCoreUiSettingsServerPluginApi", + "section": "def-common.UiSettingsServiceStart", + "text": "UiSettingsServiceStart" + } + ], + "path": "packages/kbn-reporting/server/export_type.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/reporting-server", + "id": "def-server.BaseExportTypeStartDeps.esClient", + "type": "Object", + "tags": [], + "label": "esClient", + "description": [], + "signature": [ + { + "pluginId": "@kbn/core-elasticsearch-server", + "scope": "common", + "docId": "kibKbnCoreElasticsearchServerPluginApi", + "section": "def-common.IClusterClient", + "text": "IClusterClient" + } + ], + "path": "packages/kbn-reporting/server/export_type.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/reporting-server", + "id": "def-server.BaseExportTypeStartDeps.screenshotting", + "type": "Object", + "tags": [], + "label": "screenshotting", + "description": [], + "signature": [ + { + "pluginId": "screenshotting", + "scope": "server", + "docId": "kibScreenshottingPluginApi", + "section": "def-server.ScreenshottingStart", + "text": "ScreenshottingStart" + }, + " | undefined" + ], + "path": "packages/kbn-reporting/server/export_type.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/reporting-server", + "id": "def-server.ReportingServerPluginSetup", + "type": "Interface", + "tags": [], + "label": "ReportingServerPluginSetup", + "description": [], + "path": "packages/kbn-reporting/server/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/reporting-server", + "id": "def-server.ReportingServerPluginSetup.registerExportTypes", + "type": "Function", + "tags": [], + "label": "registerExportTypes", + "description": [], + "signature": [ + "(item: ", + { + "pluginId": "@kbn/reporting-server", + "scope": "server", + "docId": "kibKbnReportingServerPluginApi", + "section": "def-server.ExportType", + "text": "ExportType" + }, + ") => void" + ], + "path": "packages/kbn-reporting/server/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/reporting-server", + "id": "def-server.ReportingServerPluginSetup.registerExportTypes.$1", + "type": "Object", + "tags": [], + "label": "item", + "description": [], + "signature": [ + { + "pluginId": "@kbn/reporting-server", + "scope": "server", + "docId": "kibKbnReportingServerPluginApi", + "section": "def-server.ExportType", + "text": "ExportType" + }, + "" + ], + "path": "packages/kbn-reporting/server/types.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/reporting-server", + "id": "def-server.ReportingServerPluginSetup.usesUiCapabilities", + "type": "Function", + "tags": [], + "label": "usesUiCapabilities", + "description": [ + "\nUsed to inform plugins if Reporting config is compatible with UI Capabilities / Application Sub-Feature Controls" + ], + "signature": [ + "() => boolean" + ], + "path": "packages/kbn-reporting/server/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [] + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/reporting-server", + "id": "def-server.TimeRangeParams", + "type": "Interface", + "tags": [], + "label": "TimeRangeParams", + "description": [], + "path": "packages/kbn-reporting/server/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/reporting-server", + "id": "def-server.TimeRangeParams.min", + "type": "CompoundType", + "tags": [], + "label": "min", + "description": [], + "signature": [ + "string | number | Date | null | undefined" + ], + "path": "packages/kbn-reporting/server/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/reporting-server", + "id": "def-server.TimeRangeParams.max", + "type": "CompoundType", + "tags": [], + "label": "max", + "description": [], + "signature": [ + "string | number | Date | null | undefined" + ], + "path": "packages/kbn-reporting/server/types.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + } + ], + "enums": [], + "misc": [ + { + "parentPluginId": "@kbn/reporting-server", + "id": "def-server.CreateJobFn", + "type": "Type", + "tags": [], + "label": "CreateJobFn", + "description": [], + "signature": [ + "(jobParams: JobParamsType, context: ", + { + "pluginId": "@kbn/core-http-request-handler-context-server", + "scope": "common", + "docId": "kibKbnCoreHttpRequestHandlerContextServerPluginApi", + "section": "def-common.CustomRequestHandlerContext", + "text": "CustomRequestHandlerContext" + }, + "<{ reporting: ", + { + "pluginId": "@kbn/reporting-server", + "scope": "server", + "docId": "kibKbnReportingServerPluginApi", + "section": "def-server.ReportingServerPluginSetup", + "text": "ReportingServerPluginSetup" + }, + " | null; }>, req: ", + { + "pluginId": "@kbn/core-http-server", + "scope": "common", + "docId": "kibKbnCoreHttpServerPluginApi", + "section": "def-common.KibanaRequest", + "text": "KibanaRequest" + }, + ") => Promise>" + ], + "path": "packages/kbn-reporting/server/types.ts", + "deprecated": false, + "trackAdoption": false, + "returnComment": [], + "children": [ + { + "parentPluginId": "@kbn/reporting-server", + "id": "def-server.CreateJobFn.$1", + "type": "Uncategorized", + "tags": [], + "label": "jobParams", + "description": [], + "signature": [ + "JobParamsType" + ], + "path": "packages/kbn-reporting/server/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/reporting-server", + "id": "def-server.CreateJobFn.$2", + "type": "CompoundType", + "tags": [], + "label": "context", + "description": [], + "signature": [ + { + "pluginId": "@kbn/core-http-request-handler-context-server", + "scope": "common", + "docId": "kibKbnCoreHttpRequestHandlerContextServerPluginApi", + "section": "def-common.RequestHandlerContext", + "text": "RequestHandlerContext" + }, + " & { reporting: Promise<", + { + "pluginId": "@kbn/reporting-server", + "scope": "server", + "docId": "kibKbnReportingServerPluginApi", + "section": "def-server.ReportingServerPluginSetup", + "text": "ReportingServerPluginSetup" + }, + " | null>; }" + ], + "path": "packages/kbn-reporting/server/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/reporting-server", + "id": "def-server.CreateJobFn.$3", + "type": "Object", + "tags": [], + "label": "req", + "description": [], + "signature": [ + { + "pluginId": "@kbn/core-http-server", + "scope": "common", + "docId": "kibKbnCoreHttpServerPluginApi", + "section": "def-common.KibanaRequest", + "text": "KibanaRequest" + }, + "" + ], + "path": "packages/kbn-reporting/server/types.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/reporting-server", + "id": "def-server.ReportingConfigType", + "type": "Type", + "tags": [], + "label": "ReportingConfigType", + "description": [], + "signature": [ + "{ readonly encryptionKey?: string | undefined; readonly enabled: boolean; readonly capture: Readonly<{} & { maxAttempts: number; }>; readonly kibanaServer: Readonly<{ hostname?: string | undefined; protocol?: string | undefined; port?: number | undefined; } & {}>; readonly queue: Readonly<{} & { timeout: number | moment.Duration; pollInterval: number | moment.Duration; indexInterval: string; pollEnabled: boolean; pollIntervalErrorMultiplier: number; }>; readonly csv: Readonly<{} & { scroll: Readonly<{} & { duration: string; size: number; }>; checkForFormulas: boolean; escapeFormulaValues: boolean; enablePanelActionDownload: boolean; maxSizeBytes: number | ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ByteSizeValue", + "text": "ByteSizeValue" + }, + "; useByteOrderMarkEncoding: boolean; }>; readonly roles: Readonly<{} & { enabled: boolean; allow: string[]; }>; readonly poll: Readonly<{} & { jobCompletionNotifier: Readonly<{} & { interval: number; intervalErrorMultiplier: number; }>; jobsRefresh: Readonly<{} & { interval: number; intervalErrorMultiplier: number; }>; }>; readonly export_types: Readonly<{} & { csv: Readonly<{} & { enabled: boolean; }>; png: Readonly<{} & { enabled: boolean; }>; pdf: Readonly<{} & { enabled: boolean; }>; }>; readonly statefulSettings: Readonly<{} & { enabled: boolean; }>; }" + ], + "path": "packages/kbn-reporting/server/types.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/reporting-server", + "id": "def-server.RunTaskFn", + "type": "Type", + "tags": [], + "label": "RunTaskFn", + "description": [], + "signature": [ + "(jobId: string, payload: TaskPayloadType, cancellationToken: ", + { + "pluginId": "@kbn/reporting-common", + "scope": "common", + "docId": "kibKbnReportingCommonPluginApi", + "section": "def-common.CancellationToken", + "text": "CancellationToken" + }, + ", stream: ", + "Writable", + ") => Promise<", + "TaskRunResult", + ">" + ], + "path": "packages/kbn-reporting/server/types.ts", + "deprecated": false, + "trackAdoption": false, + "returnComment": [], + "children": [ + { + "parentPluginId": "@kbn/reporting-server", + "id": "def-server.RunTaskFn.$1", + "type": "string", + "tags": [], + "label": "jobId", + "description": [], + "path": "packages/kbn-reporting/server/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/reporting-server", + "id": "def-server.RunTaskFn.$2", + "type": "Uncategorized", + "tags": [], + "label": "payload", + "description": [], + "signature": [ + "TaskPayloadType" + ], + "path": "packages/kbn-reporting/server/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/reporting-server", + "id": "def-server.RunTaskFn.$3", + "type": "Object", + "tags": [], + "label": "cancellationToken", + "description": [], + "signature": [ + { + "pluginId": "@kbn/reporting-common", + "scope": "common", + "docId": "kibKbnReportingCommonPluginApi", + "section": "def-common.CancellationToken", + "text": "CancellationToken" + } + ], + "path": "packages/kbn-reporting/server/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/reporting-server", + "id": "def-server.RunTaskFn.$4", + "type": "Object", + "tags": [], + "label": "stream", + "description": [], + "signature": [ + "Writable" + ], + "path": "packages/kbn-reporting/server/types.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + } + ], + "objects": [ + { + "parentPluginId": "@kbn/reporting-server", + "id": "def-server.ConfigSchema", + "type": "Object", + "tags": [], + "label": "ConfigSchema", + "description": [], + "signature": [ + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + "<{ enabled: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + "; kibanaServer: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + "<{ hostname: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + "; port: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + "; protocol: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + "; }>; queue: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + "<{ indexInterval: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + "; pollEnabled: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + "; pollInterval: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + "; pollIntervalErrorMultiplier: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + "; timeout: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + "; }>; capture: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + "<{ maxAttempts: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ConditionalType", + "text": "ConditionalType" + }, + "; }>; csv: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + "<{ checkForFormulas: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + "; escapeFormulaValues: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + "; enablePanelActionDownload: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + "; maxSizeBytes: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + "; useByteOrderMarkEncoding: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + "; scroll: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + "<{ duration: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + "; size: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + "; }>; }>; encryptionKey: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ConditionalType", + "text": "ConditionalType" + }, + "; roles: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + "<{ enabled: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ConditionalType", + "text": "ConditionalType" + }, + "; allow: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ConditionalType", + "text": "ConditionalType" + }, + "; }>; poll: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + "<{ jobCompletionNotifier: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + "<{ interval: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + "; intervalErrorMultiplier: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + "; }>; jobsRefresh: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + "<{ interval: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + "; intervalErrorMultiplier: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + "; }>; }>; export_types: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + "<{ csv: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + "<{ enabled: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + "; }>; png: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + "<{ enabled: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ConditionalType", + "text": "ConditionalType" + }, + "; }>; pdf: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + "<{ enabled: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ConditionalType", + "text": "ConditionalType" + }, + "; }>; }>; statefulSettings: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + "<{ enabled: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ConditionalType", + "text": "ConditionalType" + }, + "; }>; }>" + ], + "path": "packages/kbn-reporting/server/config_schema.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + } + ] + }, + "common": { + "classes": [], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] + } +} \ No newline at end of file diff --git a/api_docs/kbn_reporting_server.mdx b/api_docs/kbn_reporting_server.mdx new file mode 100644 index 0000000000000..d3e6352855a00 --- /dev/null +++ b/api_docs/kbn_reporting_server.mdx @@ -0,0 +1,42 @@ +--- +#### +#### 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: kibKbnReportingServerPluginApi +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: 2023-11-16 +tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/reporting-server'] +--- +import kbnReportingServerObj from './kbn_reporting_server.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 | +|-------------------|-----------|------------------------|-----------------| +| 78 | 0 | 77 | 0 | + +## Server + +### Objects + + +### Functions + + +### Classes + + +### Interfaces + + +### Consts, variables and types + + diff --git a/api_docs/kbn_resizable_layout.mdx b/api_docs/kbn_resizable_layout.mdx index 68368616241dc..a99eafa2538eb 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: 2023-11-14 +date: 2023-11-16 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/resizable-layout'] --- import kbnResizableLayoutObj from './kbn_resizable_layout.devdocs.json'; diff --git a/api_docs/kbn_rison.mdx b/api_docs/kbn_rison.mdx index 5828ffcd057eb..e7cf47e62c84e 100644 --- a/api_docs/kbn_rison.mdx +++ b/api_docs/kbn_rison.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-rison title: "@kbn/rison" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/rison plugin -date: 2023-11-14 +date: 2023-11-16 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/rison'] --- import kbnRisonObj from './kbn_rison.devdocs.json'; diff --git a/api_docs/kbn_rrule.mdx b/api_docs/kbn_rrule.mdx index 24e8bc82dec24..c93ae48160847 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: 2023-11-14 +date: 2023-11-16 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/rrule'] --- import kbnRruleObj from './kbn_rrule.devdocs.json'; diff --git a/api_docs/kbn_rule_data_utils.devdocs.json b/api_docs/kbn_rule_data_utils.devdocs.json index 9cebd966126b8..249759a3164fc 100644 --- a/api_docs/kbn_rule_data_utils.devdocs.json +++ b/api_docs/kbn_rule_data_utils.devdocs.json @@ -1699,7 +1699,7 @@ "label": "TechnicalRuleDataFieldName", "description": [], "signature": [ - "\"@timestamp\" | \"event.action\" | \"tags\" | \"kibana\" | \"kibana.alert.rule.rule_type_id\" | \"kibana.alert.rule.consumer\" | \"kibana.alert.rule.execution.uuid\" | \"kibana.alert.instance.id\" | \"kibana.alert.rule.category\" | \"kibana.alert.rule.name\" | \"kibana.alert.rule.producer\" | \"kibana.alert.rule.uuid\" | \"kibana.alert.status\" | \"kibana.alert.uuid\" | \"kibana.space_ids\" | \"event.kind\" | \"kibana.alert.action_group\" | \"kibana.alert.case_ids\" | \"kibana.alert.duration.us\" | \"kibana.alert.end\" | \"kibana.alert.flapping\" | \"kibana.alert.maintenance_window_ids\" | \"kibana.alert.reason\" | \"kibana.alert.rule.parameters\" | \"kibana.alert.rule.tags\" | \"kibana.alert.start\" | \"kibana.alert.time_range\" | \"kibana.alert.workflow_status\" | \"kibana.alert.workflow_tags\" | \"kibana.version\" | \"kibana.alert\" | \"kibana.alert.rule\" | \"kibana.alert.risk_score\" | \"kibana.alert.rule.author\" | \"kibana.alert.rule.created_at\" | \"kibana.alert.rule.created_by\" | \"kibana.alert.rule.description\" | \"kibana.alert.rule.enabled\" | \"kibana.alert.rule.from\" | \"kibana.alert.rule.interval\" | \"kibana.alert.rule.license\" | \"kibana.alert.rule.note\" | \"kibana.alert.rule.references\" | \"kibana.alert.rule.rule_id\" | \"kibana.alert.rule.rule_name_override\" | \"kibana.alert.rule.to\" | \"kibana.alert.rule.type\" | \"kibana.alert.rule.updated_at\" | \"kibana.alert.rule.updated_by\" | \"kibana.alert.rule.version\" | \"kibana.alert.severity\" | \"kibana.alert.suppression.docs_count\" | \"kibana.alert.suppression.end\" | \"kibana.alert.suppression.terms\" | \"kibana.alert.suppression.terms.field\" | \"kibana.alert.suppression.start\" | \"kibana.alert.suppression.terms.value\" | \"kibana.alert.system_status\" | \"kibana.alert.workflow_reason\" | \"kibana.alert.workflow_user\" | \"ecs.version\" | \"kibana.alert.evaluation.threshold\" | \"kibana.alert.evaluation.value\" | \"kibana.alert.context\" | \"kibana.alert.evaluation.values\" | \"kibana.alert.group\" | \"kibana.alert.group.field\" | \"kibana.alert.group.value\" | \"event.module\" | \"kibana.alert.building_block_type\" | \"kibana.alert.rule.exceptions_list\" | \"kibana.alert.rule.namespace\" | \"kibana.alert.rule.threat.framework\" | \"kibana.alert.rule.threat.tactic.id\" | \"kibana.alert.rule.threat.tactic.name\" | \"kibana.alert.rule.threat.tactic.reference\" | \"kibana.alert.rule.threat.technique.id\" | \"kibana.alert.rule.threat.technique.name\" | \"kibana.alert.rule.threat.technique.reference\" | \"kibana.alert.rule.threat.technique.subtechnique.id\" | \"kibana.alert.rule.threat.technique.subtechnique.name\" | \"kibana.alert.rule.threat.technique.subtechnique.reference\"" + "\"@timestamp\" | \"event.action\" | \"tags\" | \"kibana\" | \"kibana.alert.rule.rule_type_id\" | \"kibana.alert.rule.consumer\" | \"kibana.alert.rule.execution.uuid\" | \"kibana.alert.instance.id\" | \"kibana.alert.rule.category\" | \"kibana.alert.rule.name\" | \"kibana.alert.rule.producer\" | \"kibana.alert.rule.uuid\" | \"kibana.alert.status\" | \"kibana.alert.uuid\" | \"kibana.space_ids\" | \"event.kind\" | \"kibana.alert.action_group\" | \"kibana.alert.case_ids\" | \"kibana.alert.duration.us\" | \"kibana.alert.end\" | \"kibana.alert.flapping\" | \"kibana.alert.maintenance_window_ids\" | \"kibana.alert.reason\" | \"kibana.alert.rule.parameters\" | \"kibana.alert.rule.tags\" | \"kibana.alert.start\" | \"kibana.alert.time_range\" | \"kibana.alert.workflow_status\" | \"kibana.alert.workflow_tags\" | \"kibana.version\" | \"kibana.alert.context\" | \"kibana.alert.evaluation.threshold\" | \"kibana.alert.evaluation.value\" | \"kibana.alert.evaluation.values\" | \"kibana.alert.group\" | \"ecs.version\" | \"kibana.alert.risk_score\" | \"kibana.alert.rule.author\" | \"kibana.alert.rule.created_at\" | \"kibana.alert.rule.created_by\" | \"kibana.alert.rule.description\" | \"kibana.alert.rule.enabled\" | \"kibana.alert.rule.from\" | \"kibana.alert.rule.interval\" | \"kibana.alert.rule.license\" | \"kibana.alert.rule.note\" | \"kibana.alert.rule.references\" | \"kibana.alert.rule.rule_id\" | \"kibana.alert.rule.rule_name_override\" | \"kibana.alert.rule.to\" | \"kibana.alert.rule.type\" | \"kibana.alert.rule.updated_at\" | \"kibana.alert.rule.updated_by\" | \"kibana.alert.rule.version\" | \"kibana.alert.severity\" | \"kibana.alert.suppression.docs_count\" | \"kibana.alert.suppression.end\" | \"kibana.alert.suppression.start\" | \"kibana.alert.suppression.terms.field\" | \"kibana.alert.suppression.terms.value\" | \"kibana.alert.system_status\" | \"kibana.alert.workflow_reason\" | \"kibana.alert.workflow_user\" | \"event.module\" | \"kibana.alert.rule.threat.framework\" | \"kibana.alert.rule.threat.tactic.id\" | \"kibana.alert.rule.threat.tactic.name\" | \"kibana.alert.rule.threat.tactic.reference\" | \"kibana.alert.rule.threat.technique.id\" | \"kibana.alert.rule.threat.technique.name\" | \"kibana.alert.rule.threat.technique.reference\" | \"kibana.alert.rule.threat.technique.subtechnique.id\" | \"kibana.alert.rule.threat.technique.subtechnique.name\" | \"kibana.alert.rule.threat.technique.subtechnique.reference\" | \"kibana.alert.building_block_type\" | \"kibana.alert\" | \"kibana.alert.rule\" | \"kibana.alert.suppression.terms\" | \"kibana.alert.group.field\" | \"kibana.alert.group.value\" | \"kibana.alert.rule.exceptions_list\" | \"kibana.alert.rule.namespace\"" ], "path": "packages/kbn-rule-data-utils/src/technical_field_names.ts", "deprecated": false, diff --git a/api_docs/kbn_rule_data_utils.mdx b/api_docs/kbn_rule_data_utils.mdx index 1d60f7ecc522f..d542afec010cb 100644 --- a/api_docs/kbn_rule_data_utils.mdx +++ b/api_docs/kbn_rule_data_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-rule-data-utils title: "@kbn/rule-data-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/rule-data-utils plugin -date: 2023-11-14 +date: 2023-11-16 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 36a40d513143b..3c377155867d4 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: 2023-11-14 +date: 2023-11-16 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 7fc9350ade568..d9f68be0e350d 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: 2023-11-14 +date: 2023-11-16 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 63acff8d3cfdb..c76aff70b345b 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: 2023-11-14 +date: 2023-11-16 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/search-connectors'] --- import kbnSearchConnectorsObj from './kbn_search_connectors.devdocs.json'; diff --git a/api_docs/kbn_search_response_warnings.mdx b/api_docs/kbn_search_response_warnings.mdx index 9a2210868c348..945b2ae3e6997 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: 2023-11-14 +date: 2023-11-16 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/search-response-warnings'] --- import kbnSearchResponseWarningsObj from './kbn_search_response_warnings.devdocs.json'; diff --git a/api_docs/kbn_security_solution_features.mdx b/api_docs/kbn_security_solution_features.mdx index edf64d8ac1ac8..acfe12918e43a 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: 2023-11-14 +date: 2023-11-16 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 592b88cd817f9..83314b028e90c 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: 2023-11-14 +date: 2023-11-16 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 023124ad4972e..954e8635746a8 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: 2023-11-14 +date: 2023-11-16 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 dc4edcc94b517..8314689fb6727 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: 2023-11-14 +date: 2023-11-16 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 b6b3746d78b6b..9a5e450d64ca5 100644 --- a/api_docs/kbn_securitysolution_autocomplete.mdx +++ b/api_docs/kbn_securitysolution_autocomplete.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-autocomplete title: "@kbn/securitysolution-autocomplete" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-autocomplete plugin -date: 2023-11-14 +date: 2023-11-16 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 32d8e1bb3ffb1..a47ddc3626bed 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: 2023-11-14 +date: 2023-11-16 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 2e028b9f8b7e8..37d81e7a893d1 100644 --- a/api_docs/kbn_securitysolution_ecs.mdx +++ b/api_docs/kbn_securitysolution_ecs.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-ecs title: "@kbn/securitysolution-ecs" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-ecs plugin -date: 2023-11-14 +date: 2023-11-16 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 dff265e99b0e8..2139e894450e1 100644 --- a/api_docs/kbn_securitysolution_es_utils.mdx +++ b/api_docs/kbn_securitysolution_es_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-es-utils title: "@kbn/securitysolution-es-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-es-utils plugin -date: 2023-11-14 +date: 2023-11-16 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 9201445f3ae7d..a60e455be1903 100644 --- a/api_docs/kbn_securitysolution_exception_list_components.mdx +++ b/api_docs/kbn_securitysolution_exception_list_components.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-exception-list-components title: "@kbn/securitysolution-exception-list-components" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-exception-list-components plugin -date: 2023-11-14 +date: 2023-11-16 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_grouping.mdx b/api_docs/kbn_securitysolution_grouping.mdx index 6469b6997654e..a5f7d5a720963 100644 --- a/api_docs/kbn_securitysolution_grouping.mdx +++ b/api_docs/kbn_securitysolution_grouping.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-grouping title: "@kbn/securitysolution-grouping" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-grouping plugin -date: 2023-11-14 +date: 2023-11-16 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-grouping'] --- import kbnSecuritysolutionGroupingObj from './kbn_securitysolution_grouping.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_hook_utils.mdx b/api_docs/kbn_securitysolution_hook_utils.mdx index f13b4aa8e0c7c..1230620c33ce0 100644 --- a/api_docs/kbn_securitysolution_hook_utils.mdx +++ b/api_docs/kbn_securitysolution_hook_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-hook-utils title: "@kbn/securitysolution-hook-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-hook-utils plugin -date: 2023-11-14 +date: 2023-11-16 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 c1e5297d71da6..4d7f46b3fbae4 100644 --- a/api_docs/kbn_securitysolution_io_ts_alerting_types.mdx +++ b/api_docs/kbn_securitysolution_io_ts_alerting_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-io-ts-alerting-types title: "@kbn/securitysolution-io-ts-alerting-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-io-ts-alerting-types plugin -date: 2023-11-14 +date: 2023-11-16 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 c4c80a37d145b..72e993e176104 100644 --- a/api_docs/kbn_securitysolution_io_ts_list_types.mdx +++ b/api_docs/kbn_securitysolution_io_ts_list_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-io-ts-list-types title: "@kbn/securitysolution-io-ts-list-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-io-ts-list-types plugin -date: 2023-11-14 +date: 2023-11-16 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 4bf91e8821e4e..b8f33bd276518 100644 --- a/api_docs/kbn_securitysolution_io_ts_types.mdx +++ b/api_docs/kbn_securitysolution_io_ts_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-io-ts-types title: "@kbn/securitysolution-io-ts-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-io-ts-types plugin -date: 2023-11-14 +date: 2023-11-16 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 4d4010b4529e6..9358eaf1778c0 100644 --- a/api_docs/kbn_securitysolution_io_ts_utils.mdx +++ b/api_docs/kbn_securitysolution_io_ts_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-io-ts-utils title: "@kbn/securitysolution-io-ts-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-io-ts-utils plugin -date: 2023-11-14 +date: 2023-11-16 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 906acdfe2e218..43ff4d8d86e7c 100644 --- a/api_docs/kbn_securitysolution_list_api.mdx +++ b/api_docs/kbn_securitysolution_list_api.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-list-api title: "@kbn/securitysolution-list-api" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-list-api plugin -date: 2023-11-14 +date: 2023-11-16 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 c2489f33610ed..da004a21dfea1 100644 --- a/api_docs/kbn_securitysolution_list_constants.mdx +++ b/api_docs/kbn_securitysolution_list_constants.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-list-constants title: "@kbn/securitysolution-list-constants" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-list-constants plugin -date: 2023-11-14 +date: 2023-11-16 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 473a2cd395b8f..a89758a11264a 100644 --- a/api_docs/kbn_securitysolution_list_hooks.mdx +++ b/api_docs/kbn_securitysolution_list_hooks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-list-hooks title: "@kbn/securitysolution-list-hooks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-list-hooks plugin -date: 2023-11-14 +date: 2023-11-16 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 9b26948a81f62..ed415baa56521 100644 --- a/api_docs/kbn_securitysolution_list_utils.mdx +++ b/api_docs/kbn_securitysolution_list_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-list-utils title: "@kbn/securitysolution-list-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-list-utils plugin -date: 2023-11-14 +date: 2023-11-16 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 264f355cef384..78284029c6d3c 100644 --- a/api_docs/kbn_securitysolution_rules.mdx +++ b/api_docs/kbn_securitysolution_rules.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-rules title: "@kbn/securitysolution-rules" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-rules plugin -date: 2023-11-14 +date: 2023-11-16 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 9def5c371a6e2..d89bf951b8909 100644 --- a/api_docs/kbn_securitysolution_t_grid.mdx +++ b/api_docs/kbn_securitysolution_t_grid.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-t-grid title: "@kbn/securitysolution-t-grid" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-t-grid plugin -date: 2023-11-14 +date: 2023-11-16 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 57690f66e0efa..f1ca29e4324d7 100644 --- a/api_docs/kbn_securitysolution_utils.mdx +++ b/api_docs/kbn_securitysolution_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-utils title: "@kbn/securitysolution-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-utils plugin -date: 2023-11-14 +date: 2023-11-16 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 fb9123589d5e7..39dd797375d76 100644 --- a/api_docs/kbn_server_http_tools.mdx +++ b/api_docs/kbn_server_http_tools.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-server-http-tools title: "@kbn/server-http-tools" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/server-http-tools plugin -date: 2023-11-14 +date: 2023-11-16 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 e1001a82325d6..50fecfe29e162 100644 --- a/api_docs/kbn_server_route_repository.mdx +++ b/api_docs/kbn_server_route_repository.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-server-route-repository title: "@kbn/server-route-repository" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/server-route-repository plugin -date: 2023-11-14 +date: 2023-11-16 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 85285a3820f88..6dceb8358359c 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: 2023-11-14 +date: 2023-11-16 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 b3e1f64c312aa..9cfec64031908 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: 2023-11-14 +date: 2023-11-16 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 f26f9693cfd3c..63f0b32b0f2fd 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: 2023-11-14 +date: 2023-11-16 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 686a5ab892d5e..27dd6e08fe451 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: 2023-11-14 +date: 2023-11-16 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 2c166b89ffefd..7f594a11d155d 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: 2023-11-14 +date: 2023-11-16 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 bd6a07615b823..b50171c4b28f5 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: 2023-11-14 +date: 2023-11-16 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 6f99369d8431e..30112dfacaec2 100644 --- a/api_docs/kbn_shared_svg.mdx +++ b/api_docs/kbn_shared_svg.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-svg title: "@kbn/shared-svg" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-svg plugin -date: 2023-11-14 +date: 2023-11-16 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 5763dae073b20..0ad6bb9cae25d 100644 --- a/api_docs/kbn_shared_ux_avatar_solution.mdx +++ b/api_docs/kbn_shared_ux_avatar_solution.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-avatar-solution title: "@kbn/shared-ux-avatar-solution" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-avatar-solution plugin -date: 2023-11-14 +date: 2023-11-16 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 b105e11750d4c..4f62db815bb12 100644 --- a/api_docs/kbn_shared_ux_button_exit_full_screen.mdx +++ b/api_docs/kbn_shared_ux_button_exit_full_screen.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-button-exit-full-screen title: "@kbn/shared-ux-button-exit-full-screen" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-button-exit-full-screen plugin -date: 2023-11-14 +date: 2023-11-16 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.devdocs.json b/api_docs/kbn_shared_ux_button_toolbar.devdocs.json index 612b861b36f38..3c4e59e38b544 100644 --- a/api_docs/kbn_shared_ux_button_toolbar.devdocs.json +++ b/api_docs/kbn_shared_ux_button_toolbar.devdocs.json @@ -176,7 +176,7 @@ "label": "ToolbarButton", "description": [], "signature": [ - "({ label, type, iconSide, size, isDisabled, ...rest }: React.PropsWithChildren<", + "(props: ", { "pluginId": "@kbn/shared-ux-button-toolbar", "scope": "common", @@ -184,7 +184,7 @@ "section": "def-common.Props", "text": "Props" }, - ">) => JSX.Element" + ") => JSX.Element" ], "path": "packages/shared-ux/button_toolbar/src/buttons/toolbar_button/toolbar_button.tsx", "deprecated": false, @@ -193,12 +193,11 @@ { "parentPluginId": "@kbn/shared-ux-button-toolbar", "id": "def-common.ToolbarButton.$1", - "type": "CompoundType", + "type": "Uncategorized", "tags": [], - "label": "{\n label,\n type = 'empty',\n iconSide = 'left',\n size = 'm',\n isDisabled,\n ...rest\n}", + "label": "props", "description": [], "signature": [ - "React.PropsWithChildren<", { "pluginId": "@kbn/shared-ux-button-toolbar", "scope": "common", @@ -206,7 +205,7 @@ "section": "def-common.Props", "text": "Props" }, - ">" + "" ], "path": "packages/shared-ux/button_toolbar/src/buttons/toolbar_button/toolbar_button.tsx", "deprecated": false, @@ -431,59 +430,6 @@ ], "initialIsOpen": false }, - { - "parentPluginId": "@kbn/shared-ux-button-toolbar", - "id": "def-common.Props", - "type": "Interface", - "tags": [], - "label": "Props", - "description": [ - "\nProps for `PrimaryButton`." - ], - "signature": [ - { - "pluginId": "@kbn/shared-ux-button-toolbar", - "scope": "common", - "docId": "kibKbnSharedUxButtonToolbarPluginApi", - "section": "def-common.Props", - "text": "Props" - }, - " extends Pick<", - "EuiButtonPropsForButton", - ", \"onClick\" | \"data-test-subj\" | \"isDisabled\" | \"iconType\" | \"size\" | \"iconSide\">" - ], - "path": "packages/shared-ux/button_toolbar/src/buttons/toolbar_button/toolbar_button.tsx", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "@kbn/shared-ux-button-toolbar", - "id": "def-common.Props.label", - "type": "string", - "tags": [], - "label": "label", - "description": [], - "path": "packages/shared-ux/button_toolbar/src/buttons/toolbar_button/toolbar_button.tsx", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "@kbn/shared-ux-button-toolbar", - "id": "def-common.Props.type", - "type": "CompoundType", - "tags": [], - "label": "type", - "description": [], - "signature": [ - "ToolbarButtonTypes | undefined" - ], - "path": "packages/shared-ux/button_toolbar/src/buttons/toolbar_button/toolbar_button.tsx", - "deprecated": false, - "trackAdoption": false - } - ], - "initialIsOpen": false - }, { "parentPluginId": "@kbn/shared-ux-button-toolbar", "id": "def-common.Props", @@ -525,15 +471,32 @@ "label": "Props", "description": [], "signature": [ - "{ onClick?: React.MouseEventHandler | undefined; 'data-test-subj'?: string | undefined; isDisabled?: boolean | undefined; size?: \"m\" | \"s\" | undefined; iconSide?: ", + "{ fullWidth?: boolean | undefined; onClick?: React.MouseEventHandler | undefined; 'data-test-subj'?: string | undefined; isDisabled?: boolean | undefined; isLoading?: boolean | undefined; size?: \"m\" | \"s\" | undefined; as?: \"standard\" | undefined; fontWeight?: ToolbarButtonFontWeights | undefined; iconSide?: ", "ButtonContentIconSide", - "; }" + "; groupPosition?: ButtonPositions | undefined; hasArrow?: boolean | undefined; }" ], "path": "packages/shared-ux/button_toolbar/src/buttons/add_from_library/add_from_library.tsx", "deprecated": false, "trackAdoption": false, "initialIsOpen": false }, + { + "parentPluginId": "@kbn/shared-ux-button-toolbar", + "id": "def-common.Props", + "type": "Type", + "tags": [], + "label": "Props", + "description": [ + "\nProps for `PrimaryButton`." + ], + "signature": [ + "T extends \"iconButton\" ? ToolbarIconButton : ToolbarStandardButton" + ], + "path": "packages/shared-ux/button_toolbar/src/buttons/toolbar_button/toolbar_button.tsx", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, { "parentPluginId": "@kbn/shared-ux-button-toolbar", "id": "def-common.Props", @@ -544,7 +507,7 @@ "\nProps for `ToolbarPopover`." ], "signature": [ - "AllowedButtonProps & AllowedPopoverProps & { children: (arg: { closePopover: () => void; }) => React.ReactNode; }" + "AllowedButtonProps & AllowedPopoverProps & { children: (arg: { closePopover: () => void; }) => React.ReactNode; label: boolean | React.ReactChild | React.ReactFragment | React.ReactPortal; }" ], "path": "packages/shared-ux/button_toolbar/src/popover/popover.tsx", "deprecated": false, @@ -561,7 +524,7 @@ "type for cases with both button or a popover could be used" ], "signature": [ - "React.FunctionComponent<", + "((props: ", { "pluginId": "@kbn/shared-ux-button-toolbar", "scope": "common", @@ -569,7 +532,7 @@ "section": "def-common.Props", "text": "Props" }, - "> | (({ type, label, iconType, size, children, isDisabled, ...popover }: ", + ") => JSX.Element) | (({ type, label, iconType, size, children, isDisabled, ...popover }: ", { "pluginId": "@kbn/shared-ux-button-toolbar", "scope": "common", diff --git a/api_docs/kbn_shared_ux_button_toolbar.mdx b/api_docs/kbn_shared_ux_button_toolbar.mdx index bbdefca444867..9af0278eb636a 100644 --- a/api_docs/kbn_shared_ux_button_toolbar.mdx +++ b/api_docs/kbn_shared_ux_button_toolbar.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-button-toolbar title: "@kbn/shared-ux-button-toolbar" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-button-toolbar plugin -date: 2023-11-14 +date: 2023-11-16 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-button-toolbar'] --- import kbnSharedUxButtonToolbarObj from './kbn_shared_ux_button_toolbar.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sh | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 28 | 0 | 10 | 0 | +| 26 | 0 | 8 | 0 | ## Common diff --git a/api_docs/kbn_shared_ux_card_no_data.mdx b/api_docs/kbn_shared_ux_card_no_data.mdx index a2e610c6afc1b..2597afee40c8b 100644 --- a/api_docs/kbn_shared_ux_card_no_data.mdx +++ b/api_docs/kbn_shared_ux_card_no_data.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-card-no-data title: "@kbn/shared-ux-card-no-data" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-card-no-data plugin -date: 2023-11-14 +date: 2023-11-16 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 b515f679d1e76..42e8b367cc01c 100644 --- a/api_docs/kbn_shared_ux_card_no_data_mocks.mdx +++ b/api_docs/kbn_shared_ux_card_no_data_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-card-no-data-mocks title: "@kbn/shared-ux-card-no-data-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-card-no-data-mocks plugin -date: 2023-11-14 +date: 2023-11-16 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 363cf2756cff9..5bd9ca718f0d8 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: 2023-11-14 +date: 2023-11-16 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 cc12ddc1bcfa8..d8e841f557bec 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: 2023-11-14 +date: 2023-11-16 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 365a3ee9d406c..fc319ba7b1727 100644 --- a/api_docs/kbn_shared_ux_file_context.mdx +++ b/api_docs/kbn_shared_ux_file_context.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-file-context title: "@kbn/shared-ux-file-context" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-file-context plugin -date: 2023-11-14 +date: 2023-11-16 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 e62c9d479d1f2..5d16acbe371a8 100644 --- a/api_docs/kbn_shared_ux_file_image.mdx +++ b/api_docs/kbn_shared_ux_file_image.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-file-image title: "@kbn/shared-ux-file-image" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-file-image plugin -date: 2023-11-14 +date: 2023-11-16 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 5a8213e99ef6e..98e21161e49af 100644 --- a/api_docs/kbn_shared_ux_file_image_mocks.mdx +++ b/api_docs/kbn_shared_ux_file_image_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-file-image-mocks title: "@kbn/shared-ux-file-image-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-file-image-mocks plugin -date: 2023-11-14 +date: 2023-11-16 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 efcf586e3189b..132f52fb52ad7 100644 --- a/api_docs/kbn_shared_ux_file_mocks.mdx +++ b/api_docs/kbn_shared_ux_file_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-file-mocks title: "@kbn/shared-ux-file-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-file-mocks plugin -date: 2023-11-14 +date: 2023-11-16 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 d21979dee5dd9..3cb96a8c84b47 100644 --- a/api_docs/kbn_shared_ux_file_picker.mdx +++ b/api_docs/kbn_shared_ux_file_picker.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-file-picker title: "@kbn/shared-ux-file-picker" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-file-picker plugin -date: 2023-11-14 +date: 2023-11-16 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 6637930a2f8d9..ba5b55fe70c17 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: 2023-11-14 +date: 2023-11-16 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 c46b8c2aab8d9..36937770ff197 100644 --- a/api_docs/kbn_shared_ux_file_upload.mdx +++ b/api_docs/kbn_shared_ux_file_upload.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-file-upload title: "@kbn/shared-ux-file-upload" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-file-upload plugin -date: 2023-11-14 +date: 2023-11-16 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 a6615225173e0..538be5651a652 100644 --- a/api_docs/kbn_shared_ux_file_util.mdx +++ b/api_docs/kbn_shared_ux_file_util.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-file-util title: "@kbn/shared-ux-file-util" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-file-util plugin -date: 2023-11-14 +date: 2023-11-16 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 5b06e24d8d4ea..9b9e16d37e10c 100644 --- a/api_docs/kbn_shared_ux_link_redirect_app.mdx +++ b/api_docs/kbn_shared_ux_link_redirect_app.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-link-redirect-app title: "@kbn/shared-ux-link-redirect-app" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-link-redirect-app plugin -date: 2023-11-14 +date: 2023-11-16 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 e2e0a4d7b1941..1c9aed9177222 100644 --- a/api_docs/kbn_shared_ux_link_redirect_app_mocks.mdx +++ b/api_docs/kbn_shared_ux_link_redirect_app_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-link-redirect-app-mocks title: "@kbn/shared-ux-link-redirect-app-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-link-redirect-app-mocks plugin -date: 2023-11-14 +date: 2023-11-16 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 6dc36d51b972f..8b9880d8e2c30 100644 --- a/api_docs/kbn_shared_ux_markdown.mdx +++ b/api_docs/kbn_shared_ux_markdown.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-markdown title: "@kbn/shared-ux-markdown" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-markdown plugin -date: 2023-11-14 +date: 2023-11-16 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 0a189cf21ec86..4148f5aa9bb7d 100644 --- a/api_docs/kbn_shared_ux_markdown_mocks.mdx +++ b/api_docs/kbn_shared_ux_markdown_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-markdown-mocks title: "@kbn/shared-ux-markdown-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-markdown-mocks plugin -date: 2023-11-14 +date: 2023-11-16 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 e4020e380aaef..ce94459105031 100644 --- a/api_docs/kbn_shared_ux_page_analytics_no_data.mdx +++ b/api_docs/kbn_shared_ux_page_analytics_no_data.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-analytics-no-data title: "@kbn/shared-ux-page-analytics-no-data" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-analytics-no-data plugin -date: 2023-11-14 +date: 2023-11-16 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 0d557721641f6..0f0e2b5249369 100644 --- a/api_docs/kbn_shared_ux_page_analytics_no_data_mocks.mdx +++ b/api_docs/kbn_shared_ux_page_analytics_no_data_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-analytics-no-data-mocks title: "@kbn/shared-ux-page-analytics-no-data-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-analytics-no-data-mocks plugin -date: 2023-11-14 +date: 2023-11-16 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 f17fcbf70fa69..dfb064bb8f274 100644 --- a/api_docs/kbn_shared_ux_page_kibana_no_data.mdx +++ b/api_docs/kbn_shared_ux_page_kibana_no_data.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-kibana-no-data title: "@kbn/shared-ux-page-kibana-no-data" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-kibana-no-data plugin -date: 2023-11-14 +date: 2023-11-16 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 b540620e36062..3fcba2e9a7d10 100644 --- a/api_docs/kbn_shared_ux_page_kibana_no_data_mocks.mdx +++ b/api_docs/kbn_shared_ux_page_kibana_no_data_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-kibana-no-data-mocks title: "@kbn/shared-ux-page-kibana-no-data-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-kibana-no-data-mocks plugin -date: 2023-11-14 +date: 2023-11-16 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 e476cbbd8a26d..914f0dfe2e92b 100644 --- a/api_docs/kbn_shared_ux_page_kibana_template.mdx +++ b/api_docs/kbn_shared_ux_page_kibana_template.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-kibana-template title: "@kbn/shared-ux-page-kibana-template" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-kibana-template plugin -date: 2023-11-14 +date: 2023-11-16 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 c0322a739749b..2014e9f282395 100644 --- a/api_docs/kbn_shared_ux_page_kibana_template_mocks.mdx +++ b/api_docs/kbn_shared_ux_page_kibana_template_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-kibana-template-mocks title: "@kbn/shared-ux-page-kibana-template-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-kibana-template-mocks plugin -date: 2023-11-14 +date: 2023-11-16 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 4bfddd72293a3..24fb883d80c31 100644 --- a/api_docs/kbn_shared_ux_page_no_data.mdx +++ b/api_docs/kbn_shared_ux_page_no_data.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-no-data title: "@kbn/shared-ux-page-no-data" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-no-data plugin -date: 2023-11-14 +date: 2023-11-16 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 c72ea8c4e5d0f..05879319e3bd4 100644 --- a/api_docs/kbn_shared_ux_page_no_data_config.mdx +++ b/api_docs/kbn_shared_ux_page_no_data_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-no-data-config title: "@kbn/shared-ux-page-no-data-config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-no-data-config plugin -date: 2023-11-14 +date: 2023-11-16 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 72d71252c4671..3a5f7a3ff9acd 100644 --- a/api_docs/kbn_shared_ux_page_no_data_config_mocks.mdx +++ b/api_docs/kbn_shared_ux_page_no_data_config_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-no-data-config-mocks title: "@kbn/shared-ux-page-no-data-config-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-no-data-config-mocks plugin -date: 2023-11-14 +date: 2023-11-16 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 d70bc2621cb7e..7e3bff9e8e1fc 100644 --- a/api_docs/kbn_shared_ux_page_no_data_mocks.mdx +++ b/api_docs/kbn_shared_ux_page_no_data_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-no-data-mocks title: "@kbn/shared-ux-page-no-data-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-no-data-mocks plugin -date: 2023-11-14 +date: 2023-11-16 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 86008089ebae6..7790de025448c 100644 --- a/api_docs/kbn_shared_ux_page_solution_nav.mdx +++ b/api_docs/kbn_shared_ux_page_solution_nav.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-solution-nav title: "@kbn/shared-ux-page-solution-nav" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-solution-nav plugin -date: 2023-11-14 +date: 2023-11-16 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 0f3747fa81e37..bf75854940084 100644 --- a/api_docs/kbn_shared_ux_prompt_no_data_views.mdx +++ b/api_docs/kbn_shared_ux_prompt_no_data_views.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-prompt-no-data-views title: "@kbn/shared-ux-prompt-no-data-views" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-prompt-no-data-views plugin -date: 2023-11-14 +date: 2023-11-16 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 e0d678b372d8c..65a4f10bb7165 100644 --- a/api_docs/kbn_shared_ux_prompt_no_data_views_mocks.mdx +++ b/api_docs/kbn_shared_ux_prompt_no_data_views_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-prompt-no-data-views-mocks title: "@kbn/shared-ux-prompt-no-data-views-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-prompt-no-data-views-mocks plugin -date: 2023-11-14 +date: 2023-11-16 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 246abaabe991d..2746bdc980ce4 100644 --- a/api_docs/kbn_shared_ux_prompt_not_found.mdx +++ b/api_docs/kbn_shared_ux_prompt_not_found.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-prompt-not-found title: "@kbn/shared-ux-prompt-not-found" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-prompt-not-found plugin -date: 2023-11-14 +date: 2023-11-16 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 15d5ff893d252..3968d04cd7954 100644 --- a/api_docs/kbn_shared_ux_router.mdx +++ b/api_docs/kbn_shared_ux_router.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-router title: "@kbn/shared-ux-router" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-router plugin -date: 2023-11-14 +date: 2023-11-16 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 e81c218eee99e..5478a5d9d8c60 100644 --- a/api_docs/kbn_shared_ux_router_mocks.mdx +++ b/api_docs/kbn_shared_ux_router_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-router-mocks title: "@kbn/shared-ux-router-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-router-mocks plugin -date: 2023-11-14 +date: 2023-11-16 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 9ed678b4bba3e..0e019d281ec0c 100644 --- a/api_docs/kbn_shared_ux_storybook_config.mdx +++ b/api_docs/kbn_shared_ux_storybook_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-storybook-config title: "@kbn/shared-ux-storybook-config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-storybook-config plugin -date: 2023-11-14 +date: 2023-11-16 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 969f46d8d3160..eb9dc7a265492 100644 --- a/api_docs/kbn_shared_ux_storybook_mock.mdx +++ b/api_docs/kbn_shared_ux_storybook_mock.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-storybook-mock title: "@kbn/shared-ux-storybook-mock" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-storybook-mock plugin -date: 2023-11-14 +date: 2023-11-16 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-storybook-mock'] --- import kbnSharedUxStorybookMockObj from './kbn_shared_ux_storybook_mock.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_utility.mdx b/api_docs/kbn_shared_ux_utility.mdx index 9134e838c9530..b900f78725434 100644 --- a/api_docs/kbn_shared_ux_utility.mdx +++ b/api_docs/kbn_shared_ux_utility.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-utility title: "@kbn/shared-ux-utility" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-utility plugin -date: 2023-11-14 +date: 2023-11-16 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 c782633b8fb9b..e11a54eb98d65 100644 --- a/api_docs/kbn_slo_schema.devdocs.json +++ b/api_docs/kbn_slo_schema.devdocs.json @@ -398,7 +398,115 @@ "initialIsOpen": false } ], - "interfaces": [], + "interfaces": [ + { + "parentPluginId": "@kbn/slo-schema", + "id": "def-common.Paginated", + "type": "Interface", + "tags": [], + "label": "Paginated", + "description": [], + "signature": [ + { + "pluginId": "@kbn/slo-schema", + "scope": "common", + "docId": "kibKbnSloSchemaPluginApi", + "section": "def-common.Paginated", + "text": "Paginated" + }, + "" + ], + "path": "x-pack/packages/kbn-slo-schema/src/models/pagination.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/slo-schema", + "id": "def-common.Paginated.total", + "type": "number", + "tags": [], + "label": "total", + "description": [], + "path": "x-pack/packages/kbn-slo-schema/src/models/pagination.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/slo-schema", + "id": "def-common.Paginated.page", + "type": "number", + "tags": [], + "label": "page", + "description": [], + "path": "x-pack/packages/kbn-slo-schema/src/models/pagination.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/slo-schema", + "id": "def-common.Paginated.perPage", + "type": "number", + "tags": [], + "label": "perPage", + "description": [], + "path": "x-pack/packages/kbn-slo-schema/src/models/pagination.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/slo-schema", + "id": "def-common.Paginated.results", + "type": "Array", + "tags": [], + "label": "results", + "description": [], + "signature": [ + "T[]" + ], + "path": "x-pack/packages/kbn-slo-schema/src/models/pagination.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/slo-schema", + "id": "def-common.Pagination", + "type": "Interface", + "tags": [], + "label": "Pagination", + "description": [], + "path": "x-pack/packages/kbn-slo-schema/src/models/pagination.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/slo-schema", + "id": "def-common.Pagination.page", + "type": "number", + "tags": [], + "label": "page", + "description": [], + "path": "x-pack/packages/kbn-slo-schema/src/models/pagination.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/slo-schema", + "id": "def-common.Pagination.perPage", + "type": "number", + "tags": [], + "label": "perPage", + "description": [], + "path": "x-pack/packages/kbn-slo-schema/src/models/pagination.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + } + ], "enums": [ { "parentPluginId": "@kbn/slo-schema", @@ -621,17 +729,28 @@ }, { "parentPluginId": "@kbn/slo-schema", - "id": "def-common.FindSloDefinitionsResponse", + "id": "def-common.FindSLODefinitionsParams", "type": "Type", - "tags": [ - "private" - ], - "label": "FindSloDefinitionsResponse", - "description": [ - "\nThe response type for /internal/observability/slo/_definitions\n" + "tags": [], + "label": "FindSLODefinitionsParams", + "description": [], + "signature": [ + "{ search?: string | undefined; includeOutdatedOnly?: boolean | undefined; page?: string | undefined; perPage?: string | undefined; }" ], + "path": "x-pack/packages/kbn-slo-schema/src/rest_specs/slo.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/slo-schema", + "id": "def-common.FindSLODefinitionsResponse", + "type": "Type", + "tags": [], + "label": "FindSLODefinitionsResponse", + "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 | undefined; }; } | { type: \"sli.apm.transactionErrorRate\"; params: { environment: string; service: string; transactionType: string; transactionName: string; index: string; } & { filter?: string | undefined; }; } | { type: \"sli.kql.custom\"; params: { index: string; good: string; total: string; timestampField: string; } & { filter?: string | undefined; }; } | { type: \"sli.metric.custom\"; params: { index: string; good: { metrics: (({ name: string; aggregation: \"sum\"; field: string; } & { filter?: string | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: string | undefined; }))[]; equation: string; }; total: { metrics: (({ name: string; aggregation: \"sum\"; field: string; } & { filter?: string | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: string | undefined; }))[]; equation: string; }; timestampField: string; } & { filter?: string | undefined; }; } | { type: \"sli.metric.timeslice\"; params: { index: string; metric: { metrics: (({ name: string; aggregation: \"min\" | \"max\" | \"sum\" | \"avg\" | \"cardinality\" | \"last_value\" | \"std_deviation\"; field: string; } & { filter?: string | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: string | undefined; }) | ({ name: string; aggregation: \"percentile\"; field: string; percentile: number; } & { filter?: string | undefined; }))[]; equation: string; threshold: number; comparator: \"GT\" | \"GTE\" | \"LT\" | \"LTE\"; }; timestampField: string; } & { filter?: string | undefined; }; } | { type: \"sli.histogram.custom\"; params: { index: string; timestampField: string; good: ({ field: string; aggregation: \"value_count\"; } & { filter?: string | undefined; }) | ({ field: string; aggregation: \"range\"; from: number; to: number; } & { filter?: string | undefined; }); total: ({ field: string; aggregation: \"value_count\"; } & { filter?: string | undefined; }) | ({ field: string; aggregation: \"range\"; from: number; to: number; } & { filter?: string | undefined; }); } & { filter?: string | undefined; }; }; timeWindow: { duration: string; type: \"rolling\"; } | { duration: string; type: \"calendarAligned\"; }; budgetingMethod: \"occurrences\" | \"timeslices\"; objective: { target: number; } & { timesliceTarget?: number | undefined; timesliceWindow?: string | undefined; }; revision: number; settings: { syncDelay: string; frequency: string; }; enabled: boolean; tags: string[]; groupBy: string; createdAt: string; updatedAt: string; } & { instanceId?: 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 | undefined; }; } | { type: \"sli.apm.transactionErrorRate\"; params: { environment: string; service: string; transactionType: string; transactionName: string; index: string; } & { filter?: string | undefined; }; } | { type: \"sli.kql.custom\"; params: { index: string; good: string; total: string; timestampField: string; } & { filter?: string | undefined; }; } | { type: \"sli.metric.custom\"; params: { index: string; good: { metrics: (({ name: string; aggregation: \"sum\"; field: string; } & { filter?: string | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: string | undefined; }))[]; equation: string; }; total: { metrics: (({ name: string; aggregation: \"sum\"; field: string; } & { filter?: string | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: string | undefined; }))[]; equation: string; }; timestampField: string; } & { filter?: string | undefined; }; } | { type: \"sli.metric.timeslice\"; params: { index: string; metric: { metrics: (({ name: string; aggregation: \"min\" | \"max\" | \"sum\" | \"avg\" | \"cardinality\" | \"last_value\" | \"std_deviation\"; field: string; } & { filter?: string | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: string | undefined; }) | ({ name: string; aggregation: \"percentile\"; field: string; percentile: number; } & { filter?: string | undefined; }))[]; equation: string; threshold: number; comparator: \"GT\" | \"GTE\" | \"LT\" | \"LTE\"; }; timestampField: string; } & { filter?: string | undefined; }; } | { type: \"sli.histogram.custom\"; params: { index: string; timestampField: string; good: ({ field: string; aggregation: \"value_count\"; } & { filter?: string | undefined; }) | ({ field: string; aggregation: \"range\"; from: number; to: number; } & { filter?: string | undefined; }); total: ({ field: string; aggregation: \"value_count\"; } & { filter?: string | undefined; }) | ({ field: string; aggregation: \"range\"; from: number; to: number; } & { filter?: string | undefined; }); } & { filter?: string | undefined; }; }; timeWindow: { duration: string; type: \"rolling\"; } | { duration: string; type: \"calendarAligned\"; }; budgetingMethod: \"occurrences\" | \"timeslices\"; objective: { target: number; } & { timesliceTarget?: number | undefined; timesliceWindow?: string | undefined; }; revision: number; settings: { syncDelay: string; frequency: string; }; enabled: boolean; tags: string[]; groupBy: string; createdAt: string; updatedAt: string; version: number; } & { instanceId?: string | undefined; })[]; }" ], "path": "x-pack/packages/kbn-slo-schema/src/rest_specs/slo.ts", "deprecated": false, @@ -661,7 +780,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 | undefined; }; } | { type: \"sli.apm.transactionErrorRate\"; params: { environment: string; service: string; transactionType: string; transactionName: string; index: string; } & { filter?: string | undefined; }; } | { type: \"sli.kql.custom\"; params: { index: string; good: string; total: string; timestampField: string; } & { filter?: string | undefined; }; } | { type: \"sli.metric.custom\"; params: { index: string; good: { metrics: (({ name: string; aggregation: \"sum\"; field: string; } & { filter?: string | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: string | undefined; }))[]; equation: string; }; total: { metrics: (({ name: string; aggregation: \"sum\"; field: string; } & { filter?: string | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: string | undefined; }))[]; equation: string; }; timestampField: string; } & { filter?: string | undefined; }; } | { type: \"sli.metric.timeslice\"; params: { index: string; metric: { metrics: (({ name: string; aggregation: \"min\" | \"max\" | \"sum\" | \"avg\" | \"cardinality\" | \"last_value\" | \"std_deviation\"; field: string; } & { filter?: string | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: string | undefined; }) | ({ name: string; aggregation: \"percentile\"; field: string; percentile: number; } & { filter?: string | undefined; }))[]; equation: string; threshold: number; comparator: \"GT\" | \"GTE\" | \"LT\" | \"LTE\"; }; timestampField: string; } & { filter?: string | undefined; }; } | { type: \"sli.histogram.custom\"; params: { index: string; timestampField: string; good: ({ field: string; aggregation: \"value_count\"; } & { filter?: string | undefined; }) | ({ field: string; aggregation: \"range\"; from: number; to: number; } & { filter?: string | undefined; }); total: ({ field: string; aggregation: \"value_count\"; } & { filter?: string | undefined; }) | ({ field: string; aggregation: \"range\"; from: number; to: number; } & { filter?: string | undefined; }); } & { filter?: string | undefined; }; }; timeWindow: { duration: string; type: \"rolling\"; } | { duration: string; type: \"calendarAligned\"; }; budgetingMethod: \"occurrences\" | \"timeslices\"; objective: { target: number; } & { timesliceTarget?: number | undefined; timesliceWindow?: string | undefined; }; revision: number; settings: { syncDelay: string; frequency: string; }; enabled: boolean; tags: string[]; groupBy: string; createdAt: string; updatedAt: string; } & { instanceId?: string | undefined; } & { summary: { status: \"HEALTHY\" | \"NO_DATA\" | \"DEGRADING\" | \"VIOLATED\"; sliValue: number; errorBudget: { initial: number; consumed: number; remaining: number; isEstimated: boolean; }; }; })[]; }" + "{ 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 | undefined; }; } | { type: \"sli.apm.transactionErrorRate\"; params: { environment: string; service: string; transactionType: string; transactionName: string; index: string; } & { filter?: string | undefined; }; } | { type: \"sli.kql.custom\"; params: { index: string; good: string; total: string; timestampField: string; } & { filter?: string | undefined; }; } | { type: \"sli.metric.custom\"; params: { index: string; good: { metrics: (({ name: string; aggregation: \"sum\"; field: string; } & { filter?: string | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: string | undefined; }))[]; equation: string; }; total: { metrics: (({ name: string; aggregation: \"sum\"; field: string; } & { filter?: string | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: string | undefined; }))[]; equation: string; }; timestampField: string; } & { filter?: string | undefined; }; } | { type: \"sli.metric.timeslice\"; params: { index: string; metric: { metrics: (({ name: string; aggregation: \"min\" | \"max\" | \"sum\" | \"avg\" | \"cardinality\" | \"last_value\" | \"std_deviation\"; field: string; } & { filter?: string | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: string | undefined; }) | ({ name: string; aggregation: \"percentile\"; field: string; percentile: number; } & { filter?: string | undefined; }))[]; equation: string; threshold: number; comparator: \"GT\" | \"GTE\" | \"LT\" | \"LTE\"; }; timestampField: string; } & { filter?: string | undefined; }; } | { type: \"sli.histogram.custom\"; params: { index: string; timestampField: string; good: ({ field: string; aggregation: \"value_count\"; } & { filter?: string | undefined; }) | ({ field: string; aggregation: \"range\"; from: number; to: number; } & { filter?: string | undefined; }); total: ({ field: string; aggregation: \"value_count\"; } & { filter?: string | undefined; }) | ({ field: string; aggregation: \"range\"; from: number; to: number; } & { filter?: string | undefined; }); } & { filter?: string | undefined; }; }; timeWindow: { duration: string; type: \"rolling\"; } | { duration: string; type: \"calendarAligned\"; }; budgetingMethod: \"occurrences\" | \"timeslices\"; objective: { target: number; } & { timesliceTarget?: number | undefined; timesliceWindow?: string | undefined; }; revision: number; settings: { syncDelay: string; frequency: string; }; enabled: boolean; tags: string[]; groupBy: string; createdAt: string; updatedAt: string; version: number; } & { instanceId?: string | undefined; } & { summary: { 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/slo.ts", "deprecated": false, @@ -751,7 +870,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 | undefined; }; } | { type: \"sli.apm.transactionErrorRate\"; params: { environment: string; service: string; transactionType: string; transactionName: string; index: string; } & { filter?: string | undefined; }; } | { type: \"sli.kql.custom\"; params: { index: string; good: string; total: string; timestampField: string; } & { filter?: string | undefined; }; } | { type: \"sli.metric.custom\"; params: { index: string; good: { metrics: (({ name: string; aggregation: \"sum\"; field: string; } & { filter?: string | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: string | undefined; }))[]; equation: string; }; total: { metrics: (({ name: string; aggregation: \"sum\"; field: string; } & { filter?: string | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: string | undefined; }))[]; equation: string; }; timestampField: string; } & { filter?: string | undefined; }; } | { type: \"sli.metric.timeslice\"; params: { index: string; metric: { metrics: (({ name: string; aggregation: \"min\" | \"max\" | \"sum\" | \"avg\" | \"cardinality\" | \"last_value\" | \"std_deviation\"; field: string; } & { filter?: string | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: string | undefined; }) | ({ name: string; aggregation: \"percentile\"; field: string; percentile: number; } & { filter?: string | undefined; }))[]; equation: string; threshold: number; comparator: \"GT\" | \"GTE\" | \"LT\" | \"LTE\"; }; timestampField: string; } & { filter?: string | undefined; }; } | { type: \"sli.histogram.custom\"; params: { index: string; timestampField: string; good: ({ field: string; aggregation: \"value_count\"; } & { filter?: string | undefined; }) | ({ field: string; aggregation: \"range\"; from: number; to: number; } & { filter?: string | undefined; }); total: ({ field: string; aggregation: \"value_count\"; } & { filter?: string | undefined; }) | ({ field: string; aggregation: \"range\"; from: number; to: number; } & { filter?: string | undefined; }); } & { filter?: string | undefined; }; }; timeWindow: { duration: string; type: \"rolling\"; } | { duration: string; type: \"calendarAligned\"; }; budgetingMethod: \"occurrences\" | \"timeslices\"; objective: { target: number; } & { timesliceTarget?: number | undefined; timesliceWindow?: string | undefined; }; revision: number; settings: { syncDelay: string; frequency: string; }; enabled: boolean; tags: string[]; groupBy: string; createdAt: string; updatedAt: string; } & { instanceId?: string | undefined; } & { summary: { status: \"HEALTHY\" | \"NO_DATA\" | \"DEGRADING\" | \"VIOLATED\"; sliValue: number; errorBudget: { initial: number; consumed: number; remaining: number; isEstimated: boolean; }; }; }" + "{ 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 | undefined; }; } | { type: \"sli.apm.transactionErrorRate\"; params: { environment: string; service: string; transactionType: string; transactionName: string; index: string; } & { filter?: string | undefined; }; } | { type: \"sli.kql.custom\"; params: { index: string; good: string; total: string; timestampField: string; } & { filter?: string | undefined; }; } | { type: \"sli.metric.custom\"; params: { index: string; good: { metrics: (({ name: string; aggregation: \"sum\"; field: string; } & { filter?: string | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: string | undefined; }))[]; equation: string; }; total: { metrics: (({ name: string; aggregation: \"sum\"; field: string; } & { filter?: string | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: string | undefined; }))[]; equation: string; }; timestampField: string; } & { filter?: string | undefined; }; } | { type: \"sli.metric.timeslice\"; params: { index: string; metric: { metrics: (({ name: string; aggregation: \"min\" | \"max\" | \"sum\" | \"avg\" | \"cardinality\" | \"last_value\" | \"std_deviation\"; field: string; } & { filter?: string | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: string | undefined; }) | ({ name: string; aggregation: \"percentile\"; field: string; percentile: number; } & { filter?: string | undefined; }))[]; equation: string; threshold: number; comparator: \"GT\" | \"GTE\" | \"LT\" | \"LTE\"; }; timestampField: string; } & { filter?: string | undefined; }; } | { type: \"sli.histogram.custom\"; params: { index: string; timestampField: string; good: ({ field: string; aggregation: \"value_count\"; } & { filter?: string | undefined; }) | ({ field: string; aggregation: \"range\"; from: number; to: number; } & { filter?: string | undefined; }); total: ({ field: string; aggregation: \"value_count\"; } & { filter?: string | undefined; }) | ({ field: string; aggregation: \"range\"; from: number; to: number; } & { filter?: string | undefined; }); } & { filter?: string | undefined; }; }; timeWindow: { duration: string; type: \"rolling\"; } | { duration: string; type: \"calendarAligned\"; }; budgetingMethod: \"occurrences\" | \"timeslices\"; objective: { target: number; } & { timesliceTarget?: number | undefined; timesliceWindow?: string | undefined; }; revision: number; settings: { syncDelay: string; frequency: string; }; enabled: boolean; tags: string[]; groupBy: string; createdAt: string; updatedAt: string; version: number; } & { instanceId?: string | undefined; } & { summary: { 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/slo.ts", "deprecated": false, @@ -863,6 +982,36 @@ "trackAdoption": false, "initialIsOpen": false }, + { + "parentPluginId": "@kbn/slo-schema", + "id": "def-common.ResetSLOParams", + "type": "Type", + "tags": [], + "label": "ResetSLOParams", + "description": [], + "signature": [ + "{ id: string; }" + ], + "path": "x-pack/packages/kbn-slo-schema/src/rest_specs/slo.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/slo-schema", + "id": "def-common.ResetSLOResponse", + "type": "Type", + "tags": [], + "label": "ResetSLOResponse", + "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 | undefined; }; } | { type: \"sli.apm.transactionErrorRate\"; params: { environment: string; service: string; transactionType: string; transactionName: string; index: string; } & { filter?: string | undefined; }; } | { type: \"sli.kql.custom\"; params: { index: string; good: string; total: string; timestampField: string; } & { filter?: string | undefined; }; } | { type: \"sli.metric.custom\"; params: { index: string; good: { metrics: (({ name: string; aggregation: \"sum\"; field: string; } & { filter?: string | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: string | undefined; }))[]; equation: string; }; total: { metrics: (({ name: string; aggregation: \"sum\"; field: string; } & { filter?: string | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: string | undefined; }))[]; equation: string; }; timestampField: string; } & { filter?: string | undefined; }; } | { type: \"sli.metric.timeslice\"; params: { index: string; metric: { metrics: (({ name: string; aggregation: \"min\" | \"max\" | \"sum\" | \"avg\" | \"cardinality\" | \"last_value\" | \"std_deviation\"; field: string; } & { filter?: string | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: string | undefined; }) | ({ name: string; aggregation: \"percentile\"; field: string; percentile: number; } & { filter?: string | undefined; }))[]; equation: string; threshold: number; comparator: \"GT\" | \"GTE\" | \"LT\" | \"LTE\"; }; timestampField: string; } & { filter?: string | undefined; }; } | { type: \"sli.histogram.custom\"; params: { index: string; timestampField: string; good: ({ field: string; aggregation: \"value_count\"; } & { filter?: string | undefined; }) | ({ field: string; aggregation: \"range\"; from: number; to: number; } & { filter?: string | undefined; }); total: ({ field: string; aggregation: \"value_count\"; } & { filter?: string | undefined; }) | ({ field: string; aggregation: \"range\"; from: number; to: number; } & { filter?: string | undefined; }); } & { filter?: string | undefined; }; }; timeWindow: { duration: string; type: \"rolling\"; } | { duration: string; type: \"calendarAligned\"; }; budgetingMethod: \"occurrences\" | \"timeslices\"; objective: { target: number; } & { timesliceTarget?: number | undefined; timesliceWindow?: string | undefined; }; revision: number; settings: { syncDelay: string; frequency: string; }; enabled: boolean; tags: string[]; groupBy: string; createdAt: string; updatedAt: string; version: number; } & { instanceId?: string | undefined; }" + ], + "path": "x-pack/packages/kbn-slo-schema/src/rest_specs/slo.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, { "parentPluginId": "@kbn/slo-schema", "id": "def-common.SLOResponse", @@ -871,7 +1020,7 @@ "label": "SLOResponse", "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 | undefined; }; } | { type: \"sli.apm.transactionErrorRate\"; params: { environment: string; service: string; transactionType: string; transactionName: string; index: string; } & { filter?: string | undefined; }; } | { type: \"sli.kql.custom\"; params: { index: string; good: string; total: string; timestampField: string; } & { filter?: string | undefined; }; } | { type: \"sli.metric.custom\"; params: { index: string; good: { metrics: (({ name: string; aggregation: \"sum\"; field: string; } & { filter?: string | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: string | undefined; }))[]; equation: string; }; total: { metrics: (({ name: string; aggregation: \"sum\"; field: string; } & { filter?: string | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: string | undefined; }))[]; equation: string; }; timestampField: string; } & { filter?: string | undefined; }; } | { type: \"sli.metric.timeslice\"; params: { index: string; metric: { metrics: (({ name: string; aggregation: \"min\" | \"max\" | \"sum\" | \"avg\" | \"cardinality\" | \"last_value\" | \"std_deviation\"; field: string; } & { filter?: string | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: string | undefined; }) | ({ name: string; aggregation: \"percentile\"; field: string; percentile: number; } & { filter?: string | undefined; }))[]; equation: string; threshold: number; comparator: \"GT\" | \"GTE\" | \"LT\" | \"LTE\"; }; timestampField: string; } & { filter?: string | undefined; }; } | { type: \"sli.histogram.custom\"; params: { index: string; timestampField: string; good: ({ field: string; aggregation: \"value_count\"; } & { filter?: string | undefined; }) | ({ field: string; aggregation: \"range\"; from: number; to: number; } & { filter?: string | undefined; }); total: ({ field: string; aggregation: \"value_count\"; } & { filter?: string | undefined; }) | ({ field: string; aggregation: \"range\"; from: number; to: number; } & { filter?: string | undefined; }); } & { filter?: string | undefined; }; }; timeWindow: { duration: string; type: \"rolling\"; } | { duration: string; type: \"calendarAligned\"; }; budgetingMethod: \"occurrences\" | \"timeslices\"; objective: { target: number; } & { timesliceTarget?: number | undefined; timesliceWindow?: string | undefined; }; revision: number; settings: { syncDelay: string; frequency: string; }; enabled: boolean; tags: string[]; groupBy: string; createdAt: string; updatedAt: string; } & { instanceId?: 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 | undefined; }; } | { type: \"sli.apm.transactionErrorRate\"; params: { environment: string; service: string; transactionType: string; transactionName: string; index: string; } & { filter?: string | undefined; }; } | { type: \"sli.kql.custom\"; params: { index: string; good: string; total: string; timestampField: string; } & { filter?: string | undefined; }; } | { type: \"sli.metric.custom\"; params: { index: string; good: { metrics: (({ name: string; aggregation: \"sum\"; field: string; } & { filter?: string | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: string | undefined; }))[]; equation: string; }; total: { metrics: (({ name: string; aggregation: \"sum\"; field: string; } & { filter?: string | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: string | undefined; }))[]; equation: string; }; timestampField: string; } & { filter?: string | undefined; }; } | { type: \"sli.metric.timeslice\"; params: { index: string; metric: { metrics: (({ name: string; aggregation: \"min\" | \"max\" | \"sum\" | \"avg\" | \"cardinality\" | \"last_value\" | \"std_deviation\"; field: string; } & { filter?: string | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: string | undefined; }) | ({ name: string; aggregation: \"percentile\"; field: string; percentile: number; } & { filter?: string | undefined; }))[]; equation: string; threshold: number; comparator: \"GT\" | \"GTE\" | \"LT\" | \"LTE\"; }; timestampField: string; } & { filter?: string | undefined; }; } | { type: \"sli.histogram.custom\"; params: { index: string; timestampField: string; good: ({ field: string; aggregation: \"value_count\"; } & { filter?: string | undefined; }) | ({ field: string; aggregation: \"range\"; from: number; to: number; } & { filter?: string | undefined; }); total: ({ field: string; aggregation: \"value_count\"; } & { filter?: string | undefined; }) | ({ field: string; aggregation: \"range\"; from: number; to: number; } & { filter?: string | undefined; }); } & { filter?: string | undefined; }; }; timeWindow: { duration: string; type: \"rolling\"; } | { duration: string; type: \"calendarAligned\"; }; budgetingMethod: \"occurrences\" | \"timeslices\"; objective: { target: number; } & { timesliceTarget?: number | undefined; timesliceWindow?: string | undefined; }; revision: number; settings: { syncDelay: string; frequency: string; }; enabled: boolean; tags: string[]; groupBy: string; createdAt: string; updatedAt: string; version: number; } & { instanceId?: string | undefined; }" ], "path": "x-pack/packages/kbn-slo-schema/src/rest_specs/slo.ts", "deprecated": false, @@ -886,7 +1035,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 | undefined; }; } | { type: \"sli.apm.transactionErrorRate\"; params: { environment: string; service: string; transactionType: string; transactionName: string; index: string; } & { filter?: string | undefined; }; } | { type: \"sli.kql.custom\"; params: { index: string; good: string; total: string; timestampField: string; } & { filter?: string | undefined; }; } | { type: \"sli.metric.custom\"; params: { index: string; good: { metrics: (({ name: string; aggregation: \"sum\"; field: string; } & { filter?: string | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: string | undefined; }))[]; equation: string; }; total: { metrics: (({ name: string; aggregation: \"sum\"; field: string; } & { filter?: string | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: string | undefined; }))[]; equation: string; }; timestampField: string; } & { filter?: string | undefined; }; } | { type: \"sli.metric.timeslice\"; params: { index: string; metric: { metrics: (({ name: string; aggregation: \"min\" | \"max\" | \"sum\" | \"avg\" | \"cardinality\" | \"last_value\" | \"std_deviation\"; field: string; } & { filter?: string | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: string | undefined; }) | ({ name: string; aggregation: \"percentile\"; field: string; percentile: number; } & { filter?: string | undefined; }))[]; equation: string; threshold: number; comparator: \"GT\" | \"GTE\" | \"LT\" | \"LTE\"; }; timestampField: string; } & { filter?: string | undefined; }; } | { type: \"sli.histogram.custom\"; params: { index: string; timestampField: string; good: ({ field: string; aggregation: \"value_count\"; } & { filter?: string | undefined; }) | ({ field: string; aggregation: \"range\"; from: number; to: number; } & { filter?: string | undefined; }); total: ({ field: string; aggregation: \"value_count\"; } & { filter?: string | undefined; }) | ({ field: string; aggregation: \"range\"; from: number; to: number; } & { filter?: string | undefined; }); } & { filter?: string | undefined; }; }; timeWindow: { duration: string; type: \"rolling\"; } | { duration: string; type: \"calendarAligned\"; }; budgetingMethod: \"occurrences\" | \"timeslices\"; objective: { target: number; } & { timesliceTarget?: number | undefined; timesliceWindow?: string | undefined; }; revision: number; settings: { syncDelay: string; frequency: string; }; enabled: boolean; tags: string[]; groupBy: string; createdAt: string; updatedAt: string; } & { instanceId?: string | undefined; } & { summary: { status: \"HEALTHY\" | \"NO_DATA\" | \"DEGRADING\" | \"VIOLATED\"; sliValue: number; errorBudget: { initial: number; consumed: number; remaining: number; isEstimated: boolean; }; }; }" + "{ 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 | undefined; }; } | { type: \"sli.apm.transactionErrorRate\"; params: { environment: string; service: string; transactionType: string; transactionName: string; index: string; } & { filter?: string | undefined; }; } | { type: \"sli.kql.custom\"; params: { index: string; good: string; total: string; timestampField: string; } & { filter?: string | undefined; }; } | { type: \"sli.metric.custom\"; params: { index: string; good: { metrics: (({ name: string; aggregation: \"sum\"; field: string; } & { filter?: string | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: string | undefined; }))[]; equation: string; }; total: { metrics: (({ name: string; aggregation: \"sum\"; field: string; } & { filter?: string | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: string | undefined; }))[]; equation: string; }; timestampField: string; } & { filter?: string | undefined; }; } | { type: \"sli.metric.timeslice\"; params: { index: string; metric: { metrics: (({ name: string; aggregation: \"min\" | \"max\" | \"sum\" | \"avg\" | \"cardinality\" | \"last_value\" | \"std_deviation\"; field: string; } & { filter?: string | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: string | undefined; }) | ({ name: string; aggregation: \"percentile\"; field: string; percentile: number; } & { filter?: string | undefined; }))[]; equation: string; threshold: number; comparator: \"GT\" | \"GTE\" | \"LT\" | \"LTE\"; }; timestampField: string; } & { filter?: string | undefined; }; } | { type: \"sli.histogram.custom\"; params: { index: string; timestampField: string; good: ({ field: string; aggregation: \"value_count\"; } & { filter?: string | undefined; }) | ({ field: string; aggregation: \"range\"; from: number; to: number; } & { filter?: string | undefined; }); total: ({ field: string; aggregation: \"value_count\"; } & { filter?: string | undefined; }) | ({ field: string; aggregation: \"range\"; from: number; to: number; } & { filter?: string | undefined; }); } & { filter?: string | undefined; }; }; timeWindow: { duration: string; type: \"rolling\"; } | { duration: string; type: \"calendarAligned\"; }; budgetingMethod: \"occurrences\" | \"timeslices\"; objective: { target: number; } & { timesliceTarget?: number | undefined; timesliceWindow?: string | undefined; }; revision: number; settings: { syncDelay: string; frequency: string; }; enabled: boolean; tags: string[]; groupBy: string; createdAt: string; updatedAt: string; version: number; } & { instanceId?: string | undefined; } & { summary: { 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/slo.ts", "deprecated": false, @@ -1046,7 +1195,7 @@ "label": "UpdateSLOResponse", "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 | undefined; }; } | { type: \"sli.apm.transactionErrorRate\"; params: { environment: string; service: string; transactionType: string; transactionName: string; index: string; } & { filter?: string | undefined; }; } | { type: \"sli.kql.custom\"; params: { index: string; good: string; total: string; timestampField: string; } & { filter?: string | undefined; }; } | { type: \"sli.metric.custom\"; params: { index: string; good: { metrics: (({ name: string; aggregation: \"sum\"; field: string; } & { filter?: string | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: string | undefined; }))[]; equation: string; }; total: { metrics: (({ name: string; aggregation: \"sum\"; field: string; } & { filter?: string | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: string | undefined; }))[]; equation: string; }; timestampField: string; } & { filter?: string | undefined; }; } | { type: \"sli.metric.timeslice\"; params: { index: string; metric: { metrics: (({ name: string; aggregation: \"min\" | \"max\" | \"sum\" | \"avg\" | \"cardinality\" | \"last_value\" | \"std_deviation\"; field: string; } & { filter?: string | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: string | undefined; }) | ({ name: string; aggregation: \"percentile\"; field: string; percentile: number; } & { filter?: string | undefined; }))[]; equation: string; threshold: number; comparator: \"GT\" | \"GTE\" | \"LT\" | \"LTE\"; }; timestampField: string; } & { filter?: string | undefined; }; } | { type: \"sli.histogram.custom\"; params: { index: string; timestampField: string; good: ({ field: string; aggregation: \"value_count\"; } & { filter?: string | undefined; }) | ({ field: string; aggregation: \"range\"; from: number; to: number; } & { filter?: string | undefined; }); total: ({ field: string; aggregation: \"value_count\"; } & { filter?: string | undefined; }) | ({ field: string; aggregation: \"range\"; from: number; to: number; } & { filter?: string | undefined; }); } & { filter?: string | undefined; }; }; timeWindow: { duration: string; type: \"rolling\"; } | { duration: string; type: \"calendarAligned\"; }; budgetingMethod: \"occurrences\" | \"timeslices\"; objective: { target: number; } & { timesliceTarget?: number | undefined; timesliceWindow?: string | undefined; }; revision: number; settings: { syncDelay: string; frequency: string; }; enabled: boolean; tags: string[]; groupBy: string; createdAt: string; updatedAt: string; } & { instanceId?: 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 | undefined; }; } | { type: \"sli.apm.transactionErrorRate\"; params: { environment: string; service: string; transactionType: string; transactionName: string; index: string; } & { filter?: string | undefined; }; } | { type: \"sli.kql.custom\"; params: { index: string; good: string; total: string; timestampField: string; } & { filter?: string | undefined; }; } | { type: \"sli.metric.custom\"; params: { index: string; good: { metrics: (({ name: string; aggregation: \"sum\"; field: string; } & { filter?: string | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: string | undefined; }))[]; equation: string; }; total: { metrics: (({ name: string; aggregation: \"sum\"; field: string; } & { filter?: string | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: string | undefined; }))[]; equation: string; }; timestampField: string; } & { filter?: string | undefined; }; } | { type: \"sli.metric.timeslice\"; params: { index: string; metric: { metrics: (({ name: string; aggregation: \"min\" | \"max\" | \"sum\" | \"avg\" | \"cardinality\" | \"last_value\" | \"std_deviation\"; field: string; } & { filter?: string | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: string | undefined; }) | ({ name: string; aggregation: \"percentile\"; field: string; percentile: number; } & { filter?: string | undefined; }))[]; equation: string; threshold: number; comparator: \"GT\" | \"GTE\" | \"LT\" | \"LTE\"; }; timestampField: string; } & { filter?: string | undefined; }; } | { type: \"sli.histogram.custom\"; params: { index: string; timestampField: string; good: ({ field: string; aggregation: \"value_count\"; } & { filter?: string | undefined; }) | ({ field: string; aggregation: \"range\"; from: number; to: number; } & { filter?: string | undefined; }); total: ({ field: string; aggregation: \"value_count\"; } & { filter?: string | undefined; }) | ({ field: string; aggregation: \"range\"; from: number; to: number; } & { filter?: string | undefined; }); } & { filter?: string | undefined; }; }; timeWindow: { duration: string; type: \"rolling\"; } | { duration: string; type: \"calendarAligned\"; }; budgetingMethod: \"occurrences\" | \"timeslices\"; objective: { target: number; } & { timesliceTarget?: number | undefined; timesliceWindow?: string | undefined; }; revision: number; settings: { syncDelay: string; frequency: string; }; enabled: boolean; tags: string[]; groupBy: string; createdAt: string; updatedAt: string; version: number; } & { instanceId?: string | undefined; }" ], "path": "x-pack/packages/kbn-slo-schema/src/rest_specs/slo.ts", "deprecated": false, @@ -1945,19 +2094,21 @@ "parentPluginId": "@kbn/slo-schema", "id": "def-common.findSloDefinitionsParamsSchema", "type": "Object", - "tags": [ - "private" - ], + "tags": [], "label": "findSloDefinitionsParamsSchema", - "description": [ - "\nThe query params schema for /internal/observability/slo/_definitions\n" - ], + "description": [], "signature": [ - "TypeC", + "PartialC", "<{ query: ", - "TypeC", + "PartialC", "<{ search: ", "StringC", + "; includeOutdatedOnly: ", + "Type", + "; page: ", + "StringC", + "; perPage: ", + "StringC", "; }>; }>" ], "path": "x-pack/packages/kbn-slo-schema/src/rest_specs/slo.ts", @@ -1969,14 +2120,18 @@ "parentPluginId": "@kbn/slo-schema", "id": "def-common.findSloDefinitionsResponseSchema", "type": "Object", - "tags": [ - "private" - ], + "tags": [], "label": "findSloDefinitionsResponseSchema", - "description": [ - "\nThe response schema for /internal/observability/slo/_definitions\n" - ], + "description": [], "signature": [ + "TypeC", + "<{ page: ", + "NumberC", + "; perPage: ", + "NumberC", + "; total: ", + "NumberC", + "; results: ", "ArrayC", "<", "IntersectionC", @@ -2414,7 +2569,9 @@ "Type", "; updatedAt: ", "Type", - "; }>, ", + "; version: ", + "NumberC", + "; }>, ", "PartialC", "<{ instanceId: ", "UnionC", @@ -2422,7 +2579,7 @@ "LiteralC", "<\"*\">, ", "StringC", - "]>; }>]>>" + "]>; }>]>>; }>" ], "path": "x-pack/packages/kbn-slo-schema/src/rest_specs/slo.ts", "deprecated": false, @@ -2924,7 +3081,9 @@ "Type", "; updatedAt: ", "Type", - "; }>, ", + "; version: ", + "NumberC", + "; }>, ", "PartialC", "<{ instanceId: ", "UnionC", @@ -3924,7 +4083,9 @@ "Type", "; updatedAt: ", "Type", - "; }>, ", + "; version: ", + "NumberC", + "; }>, ", "PartialC", "<{ instanceId: ", "UnionC", @@ -4875,105 +5036,30 @@ }, { "parentPluginId": "@kbn/slo-schema", - "id": "def-common.rollingTimeWindowSchema", + "id": "def-common.resetSLOParamsSchema", "type": "Object", "tags": [], - "label": "rollingTimeWindowSchema", + "label": "resetSLOParamsSchema", "description": [], "signature": [ "TypeC", - "<{ duration: ", - "Type", - "<", - { - "pluginId": "@kbn/slo-schema", - "scope": "common", - "docId": "kibKbnSloSchemaPluginApi", - "section": "def-common.Duration", - "text": "Duration" - }, - ", string, unknown>; type: ", - "LiteralC", - "<\"rolling\">; }>" - ], - "path": "x-pack/packages/kbn-slo-schema/src/schema/time_window.ts", - "deprecated": false, - "trackAdoption": false, - "initialIsOpen": false - }, - { - "parentPluginId": "@kbn/slo-schema", - "id": "def-common.rollingTimeWindowTypeSchema", - "type": "Object", - "tags": [], - "label": "rollingTimeWindowTypeSchema", - "description": [], - "signature": [ - "LiteralC", - "<\"rolling\">" - ], - "path": "x-pack/packages/kbn-slo-schema/src/schema/time_window.ts", - "deprecated": false, - "trackAdoption": false, - "initialIsOpen": false - }, - { - "parentPluginId": "@kbn/slo-schema", - "id": "def-common.settingsSchema", - "type": "Object", - "tags": [], - "label": "settingsSchema", - "description": [], - "signature": [ + "<{ path: ", "TypeC", - "<{ syncDelay: ", - "Type", - "<", - { - "pluginId": "@kbn/slo-schema", - "scope": "common", - "docId": "kibKbnSloSchemaPluginApi", - "section": "def-common.Duration", - "text": "Duration" - }, - ", string, unknown>; frequency: ", - "Type", - "<", - { - "pluginId": "@kbn/slo-schema", - "scope": "common", - "docId": "kibKbnSloSchemaPluginApi", - "section": "def-common.Duration", - "text": "Duration" - }, - ", string, unknown>; }>" - ], - "path": "x-pack/packages/kbn-slo-schema/src/schema/slo.ts", - "deprecated": false, - "trackAdoption": false, - "initialIsOpen": false - }, - { - "parentPluginId": "@kbn/slo-schema", - "id": "def-common.sloIdSchema", - "type": "Object", - "tags": [], - "label": "sloIdSchema", - "description": [], - "signature": [ - "StringC" + "<{ id: ", + "StringC", + "; }>; }>" ], - "path": "x-pack/packages/kbn-slo-schema/src/schema/slo.ts", + "path": "x-pack/packages/kbn-slo-schema/src/rest_specs/slo.ts", "deprecated": false, "trackAdoption": false, "initialIsOpen": false }, { "parentPluginId": "@kbn/slo-schema", - "id": "def-common.sloResponseSchema", + "id": "def-common.resetSLOResponseSchema", "type": "Object", "tags": [], - "label": "sloResponseSchema", + "label": "resetSLOResponseSchema", "description": [], "signature": [ "IntersectionC", @@ -5411,7 +5497,9 @@ "Type", "; updatedAt: ", "Type", - "; }>, ", + "; version: ", + "NumberC", + "; }>, ", "PartialC", "<{ instanceId: ", "UnionC", @@ -5428,28 +5516,583 @@ }, { "parentPluginId": "@kbn/slo-schema", - "id": "def-common.sloSchema", + "id": "def-common.rollingTimeWindowSchema", "type": "Object", "tags": [], - "label": "sloSchema", + "label": "rollingTimeWindowSchema", "description": [], "signature": [ "TypeC", - "<{ id: ", - "StringC", - "; name: ", - "StringC", - "; description: ", - "StringC", - "; indicator: ", - "UnionC", - "<[", - "TypeC", - "<{ type: ", - "LiteralC", - "<\"sli.apm.transactionDuration\">; params: ", - "IntersectionC", - "<[", + "<{ duration: ", + "Type", + "<", + { + "pluginId": "@kbn/slo-schema", + "scope": "common", + "docId": "kibKbnSloSchemaPluginApi", + "section": "def-common.Duration", + "text": "Duration" + }, + ", string, unknown>; type: ", + "LiteralC", + "<\"rolling\">; }>" + ], + "path": "x-pack/packages/kbn-slo-schema/src/schema/time_window.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/slo-schema", + "id": "def-common.rollingTimeWindowTypeSchema", + "type": "Object", + "tags": [], + "label": "rollingTimeWindowTypeSchema", + "description": [], + "signature": [ + "LiteralC", + "<\"rolling\">" + ], + "path": "x-pack/packages/kbn-slo-schema/src/schema/time_window.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/slo-schema", + "id": "def-common.settingsSchema", + "type": "Object", + "tags": [], + "label": "settingsSchema", + "description": [], + "signature": [ + "TypeC", + "<{ syncDelay: ", + "Type", + "<", + { + "pluginId": "@kbn/slo-schema", + "scope": "common", + "docId": "kibKbnSloSchemaPluginApi", + "section": "def-common.Duration", + "text": "Duration" + }, + ", string, unknown>; frequency: ", + "Type", + "<", + { + "pluginId": "@kbn/slo-schema", + "scope": "common", + "docId": "kibKbnSloSchemaPluginApi", + "section": "def-common.Duration", + "text": "Duration" + }, + ", string, unknown>; }>" + ], + "path": "x-pack/packages/kbn-slo-schema/src/schema/slo.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/slo-schema", + "id": "def-common.sloIdSchema", + "type": "Object", + "tags": [], + "label": "sloIdSchema", + "description": [], + "signature": [ + "StringC" + ], + "path": "x-pack/packages/kbn-slo-schema/src/schema/slo.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/slo-schema", + "id": "def-common.sloResponseSchema", + "type": "Object", + "tags": [], + "label": "sloResponseSchema", + "description": [], + "signature": [ + "IntersectionC", + "<[", + "TypeC", + "<{ id: ", + "StringC", + "; name: ", + "StringC", + "; description: ", + "StringC", + "; indicator: ", + "UnionC", + "<[", + "TypeC", + "<{ type: ", + "LiteralC", + "<\"sli.apm.transactionDuration\">; params: ", + "IntersectionC", + "<[", + "TypeC", + "<{ environment: ", + "UnionC", + "<[", + "LiteralC", + "<\"*\">, ", + "StringC", + "]>; service: ", + "UnionC", + "<[", + "LiteralC", + "<\"*\">, ", + "StringC", + "]>; transactionType: ", + "UnionC", + "<[", + "LiteralC", + "<\"*\">, ", + "StringC", + "]>; transactionName: ", + "UnionC", + "<[", + "LiteralC", + "<\"*\">, ", + "StringC", + "]>; threshold: ", + "NumberC", + "; index: ", + "StringC", + "; }>, ", + "PartialC", + "<{ filter: ", + "StringC", + "; }>]>; }>, ", + "TypeC", + "<{ type: ", + "LiteralC", + "<\"sli.apm.transactionErrorRate\">; params: ", + "IntersectionC", + "<[", + "TypeC", + "<{ environment: ", + "UnionC", + "<[", + "LiteralC", + "<\"*\">, ", + "StringC", + "]>; service: ", + "UnionC", + "<[", + "LiteralC", + "<\"*\">, ", + "StringC", + "]>; transactionType: ", + "UnionC", + "<[", + "LiteralC", + "<\"*\">, ", + "StringC", + "]>; transactionName: ", + "UnionC", + "<[", + "LiteralC", + "<\"*\">, ", + "StringC", + "]>; index: ", + "StringC", + "; }>, ", + "PartialC", + "<{ filter: ", + "StringC", + "; }>]>; }>, ", + "TypeC", + "<{ type: ", + "LiteralC", + "<\"sli.kql.custom\">; params: ", + "IntersectionC", + "<[", + "TypeC", + "<{ index: ", + "StringC", + "; good: ", + "StringC", + "; total: ", + "StringC", + "; timestampField: ", + "StringC", + "; }>, ", + "PartialC", + "<{ filter: ", + "StringC", + "; }>]>; }>, ", + "TypeC", + "<{ type: ", + "LiteralC", + "<\"sli.metric.custom\">; params: ", + "IntersectionC", + "<[", + "TypeC", + "<{ index: ", + "StringC", + "; good: ", + "TypeC", + "<{ metrics: ", + "ArrayC", + "<", + "UnionC", + "<[", + "IntersectionC", + "<[", + "TypeC", + "<{ name: ", + "StringC", + "; aggregation: ", + "LiteralC", + "<\"sum\">; field: ", + "StringC", + "; }>, ", + "PartialC", + "<{ filter: ", + "StringC", + "; }>]>, ", + "IntersectionC", + "<[", + "TypeC", + "<{ name: ", + "StringC", + "; aggregation: ", + "LiteralC", + "<\"doc_count\">; }>, ", + "PartialC", + "<{ filter: ", + "StringC", + "; }>]>]>>; equation: ", + "StringC", + "; }>; total: ", + "TypeC", + "<{ metrics: ", + "ArrayC", + "<", + "UnionC", + "<[", + "IntersectionC", + "<[", + "TypeC", + "<{ name: ", + "StringC", + "; aggregation: ", + "LiteralC", + "<\"sum\">; field: ", + "StringC", + "; }>, ", + "PartialC", + "<{ filter: ", + "StringC", + "; }>]>, ", + "IntersectionC", + "<[", + "TypeC", + "<{ name: ", + "StringC", + "; aggregation: ", + "LiteralC", + "<\"doc_count\">; }>, ", + "PartialC", + "<{ filter: ", + "StringC", + "; }>]>]>>; equation: ", + "StringC", + "; }>; timestampField: ", + "StringC", + "; }>, ", + "PartialC", + "<{ filter: ", + "StringC", + "; }>]>; }>, ", + "TypeC", + "<{ type: ", + "LiteralC", + "<\"sli.metric.timeslice\">; params: ", + "IntersectionC", + "<[", + "TypeC", + "<{ index: ", + "StringC", + "; metric: ", + "TypeC", + "<{ metrics: ", + "ArrayC", + "<", + "UnionC", + "<[", + "IntersectionC", + "<[", + "TypeC", + "<{ name: ", + "StringC", + "; aggregation: ", + "KeyofC", + "<{ avg: boolean; max: boolean; min: boolean; sum: boolean; cardinality: boolean; last_value: boolean; std_deviation: boolean; }>; field: ", + "StringC", + "; }>, ", + "PartialC", + "<{ filter: ", + "StringC", + "; }>]>, ", + "IntersectionC", + "<[", + "TypeC", + "<{ name: ", + "StringC", + "; aggregation: ", + "LiteralC", + "<\"doc_count\">; }>, ", + "PartialC", + "<{ filter: ", + "StringC", + "; }>]>, ", + "IntersectionC", + "<[", + "TypeC", + "<{ name: ", + "StringC", + "; aggregation: ", + "LiteralC", + "<\"percentile\">; field: ", + "StringC", + "; percentile: ", + "NumberC", + "; }>, ", + "PartialC", + "<{ filter: ", + "StringC", + "; }>]>]>>; equation: ", + "StringC", + "; threshold: ", + "NumberC", + "; comparator: ", + "KeyofC", + "<{ GT: string; GTE: string; LT: string; LTE: string; }>; }>; timestampField: ", + "StringC", + "; }>, ", + "PartialC", + "<{ filter: ", + "StringC", + "; }>]>; }>, ", + "TypeC", + "<{ type: ", + "LiteralC", + "<\"sli.histogram.custom\">; params: ", + "IntersectionC", + "<[", + "TypeC", + "<{ index: ", + "StringC", + "; timestampField: ", + "StringC", + "; good: ", + "UnionC", + "<[", + "IntersectionC", + "<[", + "TypeC", + "<{ field: ", + "StringC", + "; aggregation: ", + "LiteralC", + "<\"value_count\">; }>, ", + "PartialC", + "<{ filter: ", + "StringC", + "; }>]>, ", + "IntersectionC", + "<[", + "TypeC", + "<{ field: ", + "StringC", + "; aggregation: ", + "LiteralC", + "<\"range\">; from: ", + "NumberC", + "; to: ", + "NumberC", + "; }>, ", + "PartialC", + "<{ filter: ", + "StringC", + "; }>]>]>; total: ", + "UnionC", + "<[", + "IntersectionC", + "<[", + "TypeC", + "<{ field: ", + "StringC", + "; aggregation: ", + "LiteralC", + "<\"value_count\">; }>, ", + "PartialC", + "<{ filter: ", + "StringC", + "; }>]>, ", + "IntersectionC", + "<[", + "TypeC", + "<{ field: ", + "StringC", + "; aggregation: ", + "LiteralC", + "<\"range\">; from: ", + "NumberC", + "; to: ", + "NumberC", + "; }>, ", + "PartialC", + "<{ filter: ", + "StringC", + "; }>]>]>; }>, ", + "PartialC", + "<{ filter: ", + "StringC", + "; }>]>; }>]>; timeWindow: ", + "UnionC", + "<[", + "TypeC", + "<{ duration: ", + "Type", + "<", + { + "pluginId": "@kbn/slo-schema", + "scope": "common", + "docId": "kibKbnSloSchemaPluginApi", + "section": "def-common.Duration", + "text": "Duration" + }, + ", string, unknown>; type: ", + "LiteralC", + "<\"rolling\">; }>, ", + "TypeC", + "<{ duration: ", + "Type", + "<", + { + "pluginId": "@kbn/slo-schema", + "scope": "common", + "docId": "kibKbnSloSchemaPluginApi", + "section": "def-common.Duration", + "text": "Duration" + }, + ", string, unknown>; type: ", + "LiteralC", + "<\"calendarAligned\">; }>]>; budgetingMethod: ", + "UnionC", + "<[", + "LiteralC", + "<\"occurrences\">, ", + "LiteralC", + "<\"timeslices\">]>; objective: ", + "IntersectionC", + "<[", + "TypeC", + "<{ target: ", + "NumberC", + "; }>, ", + "PartialC", + "<{ timesliceTarget: ", + "NumberC", + "; timesliceWindow: ", + "Type", + "<", + { + "pluginId": "@kbn/slo-schema", + "scope": "common", + "docId": "kibKbnSloSchemaPluginApi", + "section": "def-common.Duration", + "text": "Duration" + }, + ", string, unknown>; }>]>; revision: ", + "NumberC", + "; settings: ", + "TypeC", + "<{ syncDelay: ", + "Type", + "<", + { + "pluginId": "@kbn/slo-schema", + "scope": "common", + "docId": "kibKbnSloSchemaPluginApi", + "section": "def-common.Duration", + "text": "Duration" + }, + ", string, unknown>; frequency: ", + "Type", + "<", + { + "pluginId": "@kbn/slo-schema", + "scope": "common", + "docId": "kibKbnSloSchemaPluginApi", + "section": "def-common.Duration", + "text": "Duration" + }, + ", string, unknown>; }>; enabled: ", + "BooleanC", + "; tags: ", + "ArrayC", + "<", + "StringC", + ">; groupBy: ", + "UnionC", + "<[", + "LiteralC", + "<\"*\">, ", + "StringC", + "]>; createdAt: ", + "Type", + "; updatedAt: ", + "Type", + "; version: ", + "NumberC", + "; }>, ", + "PartialC", + "<{ instanceId: ", + "UnionC", + "<[", + "LiteralC", + "<\"*\">, ", + "StringC", + "]>; }>]>" + ], + "path": "x-pack/packages/kbn-slo-schema/src/rest_specs/slo.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/slo-schema", + "id": "def-common.sloSchema", + "type": "Object", + "tags": [], + "label": "sloSchema", + "description": [], + "signature": [ + "TypeC", + "<{ id: ", + "StringC", + "; name: ", + "StringC", + "; description: ", + "StringC", + "; indicator: ", + "UnionC", + "<[", + "TypeC", + "<{ type: ", + "LiteralC", + "<\"sli.apm.transactionDuration\">; params: ", + "IntersectionC", + "<[", "TypeC", "<{ environment: ", "UnionC", @@ -5867,7 +6510,9 @@ "LiteralC", "<\"*\">, ", "StringC", - "]>; }>" + "]>; version: ", + "NumberC", + "; }>" ], "path": "x-pack/packages/kbn-slo-schema/src/schema/slo.ts", "deprecated": false, @@ -6319,7 +6964,9 @@ "Type", "; updatedAt: ", "Type", - "; }>, ", + "; version: ", + "NumberC", + "; }>, ", "PartialC", "<{ instanceId: ", "UnionC", @@ -6803,7 +7450,9 @@ "LiteralC", "<\"*\">, ", "StringC", - "]>; }>, ", + "]>; version: ", + "NumberC", + "; }>, ", "TypeC", "<{ summary: ", "TypeC", @@ -8201,7 +8850,9 @@ "Type", "; updatedAt: ", "Type", - "; }>, ", + "; version: ", + "NumberC", + "; }>, ", "PartialC", "<{ instanceId: ", "UnionC", diff --git a/api_docs/kbn_slo_schema.mdx b/api_docs/kbn_slo_schema.mdx index 658a36e7a5577..7c42b258ebdeb 100644 --- a/api_docs/kbn_slo_schema.mdx +++ b/api_docs/kbn_slo_schema.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-slo-schema title: "@kbn/slo-schema" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/slo-schema plugin -date: 2023-11-14 +date: 2023-11-16 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/slo-schema'] --- import kbnSloSchemaObj from './kbn_slo_schema.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/obs-ux-management-team](https://github.com/orgs/elastic/teams/ | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 131 | 0 | 128 | 0 | +| 144 | 0 | 144 | 0 | ## Common @@ -34,6 +34,9 @@ Contact [@elastic/obs-ux-management-team](https://github.com/orgs/elastic/teams/ ### Classes +### Interfaces + + ### Enums diff --git a/api_docs/kbn_some_dev_log.mdx b/api_docs/kbn_some_dev_log.mdx index 939cb0de4e4d8..7fee4e17d1c91 100644 --- a/api_docs/kbn_some_dev_log.mdx +++ b/api_docs/kbn_some_dev_log.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-some-dev-log title: "@kbn/some-dev-log" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/some-dev-log plugin -date: 2023-11-14 +date: 2023-11-16 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/some-dev-log'] --- import kbnSomeDevLogObj from './kbn_some_dev_log.devdocs.json'; diff --git a/api_docs/kbn_std.mdx b/api_docs/kbn_std.mdx index e8af86b302e01..23e06f334a209 100644 --- a/api_docs/kbn_std.mdx +++ b/api_docs/kbn_std.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-std title: "@kbn/std" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/std plugin -date: 2023-11-14 +date: 2023-11-16 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 f061dca223b40..cd6b795dc72c6 100644 --- a/api_docs/kbn_stdio_dev_helpers.mdx +++ b/api_docs/kbn_stdio_dev_helpers.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-stdio-dev-helpers title: "@kbn/stdio-dev-helpers" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/stdio-dev-helpers plugin -date: 2023-11-14 +date: 2023-11-16 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 92447103fa41c..c6d366d7393e4 100644 --- a/api_docs/kbn_storybook.mdx +++ b/api_docs/kbn_storybook.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-storybook title: "@kbn/storybook" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/storybook plugin -date: 2023-11-14 +date: 2023-11-16 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/storybook'] --- import kbnStorybookObj from './kbn_storybook.devdocs.json'; diff --git a/api_docs/kbn_subscription_tracking.mdx b/api_docs/kbn_subscription_tracking.mdx index 66b95e752d61f..ab44c4c5278cc 100644 --- a/api_docs/kbn_subscription_tracking.mdx +++ b/api_docs/kbn_subscription_tracking.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-subscription-tracking title: "@kbn/subscription-tracking" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/subscription-tracking plugin -date: 2023-11-14 +date: 2023-11-16 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/subscription-tracking'] --- import kbnSubscriptionTrackingObj from './kbn_subscription_tracking.devdocs.json'; diff --git a/api_docs/kbn_telemetry_tools.mdx b/api_docs/kbn_telemetry_tools.mdx index 8115b6a7db015..0945a0e2d111c 100644 --- a/api_docs/kbn_telemetry_tools.mdx +++ b/api_docs/kbn_telemetry_tools.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-telemetry-tools title: "@kbn/telemetry-tools" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/telemetry-tools plugin -date: 2023-11-14 +date: 2023-11-16 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 68d2bf7d151de..69bba2fc1f846 100644 --- a/api_docs/kbn_test.mdx +++ b/api_docs/kbn_test.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-test title: "@kbn/test" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/test plugin -date: 2023-11-14 +date: 2023-11-16 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/test'] --- import kbnTestObj from './kbn_test.devdocs.json'; diff --git a/api_docs/kbn_test_jest_helpers.mdx b/api_docs/kbn_test_jest_helpers.mdx index 4b454877a185a..2901e719fe490 100644 --- a/api_docs/kbn_test_jest_helpers.mdx +++ b/api_docs/kbn_test_jest_helpers.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-test-jest-helpers title: "@kbn/test-jest-helpers" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/test-jest-helpers plugin -date: 2023-11-14 +date: 2023-11-16 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 3864032beae99..1764322c812e6 100644 --- a/api_docs/kbn_test_subj_selector.mdx +++ b/api_docs/kbn_test_subj_selector.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-test-subj-selector title: "@kbn/test-subj-selector" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/test-subj-selector plugin -date: 2023-11-14 +date: 2023-11-16 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 0604a8948c76f..e530782988665 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: 2023-11-14 +date: 2023-11-16 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/text-based-editor'] --- import kbnTextBasedEditorObj from './kbn_text_based_editor.devdocs.json'; diff --git a/api_docs/kbn_tooling_log.mdx b/api_docs/kbn_tooling_log.mdx index d095d3975d772..8658e8c3dd4ac 100644 --- a/api_docs/kbn_tooling_log.mdx +++ b/api_docs/kbn_tooling_log.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-tooling-log title: "@kbn/tooling-log" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/tooling-log plugin -date: 2023-11-14 +date: 2023-11-16 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/tooling-log'] --- import kbnToolingLogObj from './kbn_tooling_log.devdocs.json'; diff --git a/api_docs/kbn_ts_projects.mdx b/api_docs/kbn_ts_projects.mdx index 7b41d6d13485b..9ced7a66855bc 100644 --- a/api_docs/kbn_ts_projects.mdx +++ b/api_docs/kbn_ts_projects.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ts-projects title: "@kbn/ts-projects" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ts-projects plugin -date: 2023-11-14 +date: 2023-11-16 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 73f801719623b..77bdb5f91fd4c 100644 --- a/api_docs/kbn_typed_react_router_config.mdx +++ b/api_docs/kbn_typed_react_router_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-typed-react-router-config title: "@kbn/typed-react-router-config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/typed-react-router-config plugin -date: 2023-11-14 +date: 2023-11-16 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 9ad6acd3b38f1..1274bf25fa9c1 100644 --- a/api_docs/kbn_ui_actions_browser.mdx +++ b/api_docs/kbn_ui_actions_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ui-actions-browser title: "@kbn/ui-actions-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ui-actions-browser plugin -date: 2023-11-14 +date: 2023-11-16 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 1786e1b5c0655..e9f159428e46a 100644 --- a/api_docs/kbn_ui_shared_deps_src.mdx +++ b/api_docs/kbn_ui_shared_deps_src.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ui-shared-deps-src title: "@kbn/ui-shared-deps-src" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ui-shared-deps-src plugin -date: 2023-11-14 +date: 2023-11-16 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 8b67980d45be6..04a49d7347080 100644 --- a/api_docs/kbn_ui_theme.mdx +++ b/api_docs/kbn_ui_theme.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ui-theme title: "@kbn/ui-theme" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ui-theme plugin -date: 2023-11-14 +date: 2023-11-16 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 3924ff9874f60..6becec7972d24 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: 2023-11-14 +date: 2023-11-16 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 178310716afe5..8cf7199ed233e 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: 2023-11-14 +date: 2023-11-16 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 de775d2cf01c4..81aa7a60b9cf7 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: 2023-11-14 +date: 2023-11-16 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 b7288834bf3d1..6c364636d653b 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: 2023-11-14 +date: 2023-11-16 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/unsaved-changes-badge'] --- import kbnUnsavedChangesBadgeObj from './kbn_unsaved_changes_badge.devdocs.json'; diff --git a/api_docs/kbn_url_state.mdx b/api_docs/kbn_url_state.mdx index 2e843d2220047..840b0a4977193 100644 --- a/api_docs/kbn_url_state.mdx +++ b/api_docs/kbn_url_state.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-url-state title: "@kbn/url-state" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/url-state plugin -date: 2023-11-14 +date: 2023-11-16 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/url-state'] --- import kbnUrlStateObj from './kbn_url_state.devdocs.json'; diff --git a/api_docs/kbn_use_tracked_promise.mdx b/api_docs/kbn_use_tracked_promise.mdx index f98d1352fe262..d786478df658c 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: 2023-11-14 +date: 2023-11-16 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.devdocs.json b/api_docs/kbn_user_profile_components.devdocs.json index 8a2a61616e98d..e3e6876539109 100644 --- a/api_docs/kbn_user_profile_components.devdocs.json +++ b/api_docs/kbn_user_profile_components.devdocs.json @@ -560,7 +560,7 @@ }, " extends Omit<", "EuiAvatarProps", - ", \"type\" | \"name\" | \"color\" | \"iconType\" | \"iconColor\" | \"iconSize\" | \"initials\" | \"initialsLength\" | \"imageUrl\">" + ", \"type\" | \"name\" | \"color\" | \"iconType\" | \"iconColor\" | \"initials\" | \"initialsLength\" | \"imageUrl\" | \"iconSize\">" ], "path": "packages/kbn-user-profile-components/src/user_avatar.tsx", "deprecated": false, diff --git a/api_docs/kbn_user_profile_components.mdx b/api_docs/kbn_user_profile_components.mdx index 9e295e400b345..f7a5f71a4cc1a 100644 --- a/api_docs/kbn_user_profile_components.mdx +++ b/api_docs/kbn_user_profile_components.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-user-profile-components title: "@kbn/user-profile-components" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/user-profile-components plugin -date: 2023-11-14 +date: 2023-11-16 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 98be76ef15e90..e7e71b57227d2 100644 --- a/api_docs/kbn_utility_types.mdx +++ b/api_docs/kbn_utility_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-utility-types title: "@kbn/utility-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/utility-types plugin -date: 2023-11-14 +date: 2023-11-16 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 9e812c8bebbc4..f9667564988d4 100644 --- a/api_docs/kbn_utility_types_jest.mdx +++ b/api_docs/kbn_utility_types_jest.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-utility-types-jest title: "@kbn/utility-types-jest" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/utility-types-jest plugin -date: 2023-11-14 +date: 2023-11-16 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 136525ee71657..bb87f0b1f130b 100644 --- a/api_docs/kbn_utils.mdx +++ b/api_docs/kbn_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-utils title: "@kbn/utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/utils plugin -date: 2023-11-14 +date: 2023-11-16 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/utils'] --- import kbnUtilsObj from './kbn_utils.devdocs.json'; diff --git a/api_docs/kbn_visualization_ui_components.devdocs.json b/api_docs/kbn_visualization_ui_components.devdocs.json index 80a90a0b589f6..bd1f417ecd328 100644 --- a/api_docs/kbn_visualization_ui_components.devdocs.json +++ b/api_docs/kbn_visualization_ui_components.devdocs.json @@ -1978,38 +1978,6 @@ "returnComment": [], "initialIsOpen": false }, - { - "parentPluginId": "@kbn/visualization-ui-components", - "id": "def-public.TruncatedLabel", - "type": "Function", - "tags": [], - "label": "TruncatedLabel", - "description": [], - "signature": [ - "React.NamedExoticComponent<{ label: string; search: string; width: number; font: string; }>" - ], - "path": "packages/kbn-visualization-ui-components/components/field_picker/truncated_label.tsx", - "deprecated": false, - "trackAdoption": false, - "returnComment": [], - "children": [ - { - "parentPluginId": "@kbn/visualization-ui-components", - "id": "def-public.TruncatedLabel.$1", - "type": "Uncategorized", - "tags": [], - "label": "props", - "description": [], - "signature": [ - "P" - ], - "path": "node_modules/@types/react/index.d.ts", - "deprecated": false, - "trackAdoption": false - } - ], - "initialIsOpen": false - }, { "parentPluginId": "@kbn/visualization-ui-components", "id": "def-public.useDebouncedValue", diff --git a/api_docs/kbn_visualization_ui_components.mdx b/api_docs/kbn_visualization_ui_components.mdx index 5fd96b04dfad5..542a0bbbca634 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: 2023-11-14 +date: 2023-11-16 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/visualization-ui-components'] --- import kbnVisualizationUiComponentsObj from './kbn_visualization_ui_components.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 | |-------------------|-----------|------------------------|-----------------| -| 156 | 0 | 152 | 3 | +| 154 | 0 | 151 | 3 | ## Client diff --git a/api_docs/kbn_xstate_utils.mdx b/api_docs/kbn_xstate_utils.mdx index 85e133e7385e7..e762b217c8364 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: 2023-11-14 +date: 2023-11-16 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 503adf690614d..7b7f033b237ea 100644 --- a/api_docs/kbn_yarn_lock_validator.mdx +++ b/api_docs/kbn_yarn_lock_validator.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-yarn-lock-validator title: "@kbn/yarn-lock-validator" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/yarn-lock-validator plugin -date: 2023-11-14 +date: 2023-11-16 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 c37ec591dd9f2..a37c31eea3823 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: 2023-11-14 +date: 2023-11-16 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 b9eec34a815c7..5e4d81d7129a2 100644 --- a/api_docs/kibana_overview.mdx +++ b/api_docs/kibana_overview.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kibanaOverview title: "kibanaOverview" image: https://source.unsplash.com/400x175/?github description: API docs for the kibanaOverview plugin -date: 2023-11-14 +date: 2023-11-16 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'kibanaOverview'] --- import kibanaOverviewObj from './kibana_overview.devdocs.json'; diff --git a/api_docs/kibana_react.devdocs.json b/api_docs/kibana_react.devdocs.json index 1620ff10dea39..4cc2a07f5bad4 100644 --- a/api_docs/kibana_react.devdocs.json +++ b/api_docs/kibana_react.devdocs.json @@ -2562,59 +2562,59 @@ }, { "plugin": "data", - "path": "src/plugins/data/public/search/search_interceptor/search_interceptor.ts" + "path": "src/plugins/data/public/search/session/sessions_mgmt/components/actions/delete_button.tsx" }, { "plugin": "data", - "path": "src/plugins/data/public/search/search_interceptor/search_interceptor.ts" + "path": "src/plugins/data/public/search/session/sessions_mgmt/components/actions/delete_button.tsx" }, { "plugin": "data", - "path": "src/plugins/data/public/search/search_interceptor/search_interceptor.ts" + "path": "src/plugins/data/public/search/session/sessions_mgmt/components/actions/extend_button.tsx" }, { "plugin": "data", - "path": "src/plugins/data/public/search/search_interceptor/search_interceptor.ts" + "path": "src/plugins/data/public/search/session/sessions_mgmt/components/actions/extend_button.tsx" }, { "plugin": "data", - "path": "src/plugins/data/public/search/session/sessions_mgmt/components/actions/delete_button.tsx" + "path": "src/plugins/data/public/search/session/sessions_mgmt/components/actions/inspect_button.tsx" }, { "plugin": "data", - "path": "src/plugins/data/public/search/session/sessions_mgmt/components/actions/delete_button.tsx" + "path": "src/plugins/data/public/search/session/sessions_mgmt/components/actions/inspect_button.tsx" }, { "plugin": "data", - "path": "src/plugins/data/public/search/session/sessions_mgmt/components/actions/extend_button.tsx" + "path": "src/plugins/data/public/search/session/sessions_mgmt/components/actions/rename_button.tsx" }, { "plugin": "data", - "path": "src/plugins/data/public/search/session/sessions_mgmt/components/actions/extend_button.tsx" + "path": "src/plugins/data/public/search/session/sessions_mgmt/components/actions/rename_button.tsx" }, { "plugin": "data", - "path": "src/plugins/data/public/search/session/sessions_mgmt/components/actions/inspect_button.tsx" + "path": "src/plugins/data/public/search/search_service.ts" }, { "plugin": "data", - "path": "src/plugins/data/public/search/session/sessions_mgmt/components/actions/inspect_button.tsx" + "path": "src/plugins/data/public/search/search_service.ts" }, { "plugin": "data", - "path": "src/plugins/data/public/search/session/sessions_mgmt/components/actions/rename_button.tsx" + "path": "src/plugins/data/public/search/search_interceptor/search_interceptor.ts" }, { "plugin": "data", - "path": "src/plugins/data/public/search/session/sessions_mgmt/components/actions/rename_button.tsx" + "path": "src/plugins/data/public/search/search_interceptor/search_interceptor.ts" }, { "plugin": "data", - "path": "src/plugins/data/public/search/search_service.ts" + "path": "src/plugins/data/public/search/search_interceptor/search_interceptor.ts" }, { "plugin": "data", - "path": "src/plugins/data/public/search/search_service.ts" + "path": "src/plugins/data/public/search/search_interceptor/search_interceptor.ts" }, { "plugin": "savedObjects", @@ -3538,55 +3538,6 @@ "returnComment": [], "initialIsOpen": false }, - { - "parentPluginId": "kibanaReact", - "id": "def-public.ToolbarButton", - "type": "Function", - "tags": [], - "label": "ToolbarButton", - "description": [], - "signature": [ - "({ children, className, fontWeight, size, hasArrow, groupPosition, dataTestSubj, ...rest }: React.PropsWithChildren<", - { - "pluginId": "kibanaReact", - "scope": "public", - "docId": "kibKibanaReactPluginApi", - "section": "def-public.ToolbarButtonProps", - "text": "ToolbarButtonProps" - }, - ">) => JSX.Element" - ], - "path": "src/plugins/kibana_react/public/toolbar_button/toolbar_button.tsx", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "kibanaReact", - "id": "def-public.ToolbarButton.$1", - "type": "CompoundType", - "tags": [], - "label": "{\n children,\n className,\n fontWeight = 'normal',\n size = 'm',\n hasArrow = true,\n groupPosition = 'none',\n dataTestSubj = '',\n ...rest\n}", - "description": [], - "signature": [ - "React.PropsWithChildren<", - { - "pluginId": "kibanaReact", - "scope": "public", - "docId": "kibKibanaReactPluginApi", - "section": "def-public.ToolbarButtonProps", - "text": "ToolbarButtonProps" - }, - ">" - ], - "path": "src/plugins/kibana_react/public/toolbar_button/toolbar_button.tsx", - "deprecated": false, - "trackAdoption": false, - "isRequired": true - } - ], - "returnComment": [], - "initialIsOpen": false - }, { "parentPluginId": "kibanaReact", "id": "def-public.UrlTemplateEditor", @@ -5336,67 +5287,6 @@ "trackAdoption": false, "initialIsOpen": false }, - { - "parentPluginId": "kibanaReact", - "id": "def-public.POSITIONS", - "type": "Array", - "tags": [], - "label": "POSITIONS", - "description": [], - "signature": [ - "(\"none\" | \"right\" | \"left\" | \"center\")[]" - ], - "path": "src/plugins/kibana_react/public/toolbar_button/toolbar_button.tsx", - "deprecated": false, - "trackAdoption": false, - "initialIsOpen": false - }, - { - "parentPluginId": "kibanaReact", - "id": "def-public.TOOLBAR_BUTTON_SIZES", - "type": "Array", - "tags": [], - "label": "TOOLBAR_BUTTON_SIZES", - "description": [], - "signature": [ - "(\"m\" | \"s\" | undefined)[]" - ], - "path": "src/plugins/kibana_react/public/toolbar_button/toolbar_button.tsx", - "deprecated": false, - "trackAdoption": false, - "initialIsOpen": false - }, - { - "parentPluginId": "kibanaReact", - "id": "def-public.ToolbarButtonProps", - "type": "Type", - "tags": [], - "label": "ToolbarButtonProps", - "description": [], - "signature": [ - "((", - "DisambiguateSet", - "<", - "EuiButtonPropsForAnchor", - ", ", - "EuiButtonPropsForButton", - "> & ", - "EuiButtonProps", - " & { onClick?: React.MouseEventHandler | undefined; } & React.ButtonHTMLAttributes & { buttonRef?: React.Ref | undefined; }) | (", - "DisambiguateSet", - "<", - "EuiButtonPropsForButton", - ", ", - "EuiButtonPropsForAnchor", - "> & ", - "EuiButtonProps", - " & { href?: string | undefined; onClick?: React.MouseEventHandler | undefined; } & React.AnchorHTMLAttributes & { buttonRef?: React.Ref | undefined; })) & { fontWeight?: Weights | undefined; size?: \"m\" | \"s\" | undefined; hasArrow?: boolean | undefined; groupPosition?: \"none\" | \"right\" | \"left\" | \"center\" | undefined; dataTestSubj?: string | undefined; }" - ], - "path": "src/plugins/kibana_react/public/toolbar_button/toolbar_button.tsx", - "deprecated": false, - "trackAdoption": false, - "initialIsOpen": false - }, { "parentPluginId": "kibanaReact", "id": "def-public.Value", @@ -5411,21 +5301,6 @@ "deprecated": false, "trackAdoption": false, "initialIsOpen": false - }, - { - "parentPluginId": "kibanaReact", - "id": "def-public.WEIGHTS", - "type": "Array", - "tags": [], - "label": "WEIGHTS", - "description": [], - "signature": [ - "Weights[]" - ], - "path": "src/plugins/kibana_react/public/toolbar_button/toolbar_button.tsx", - "deprecated": false, - "trackAdoption": false, - "initialIsOpen": false } ], "objects": [ diff --git a/api_docs/kibana_react.mdx b/api_docs/kibana_react.mdx index b44c52dad3974..2de9cf5fc0879 100644 --- a/api_docs/kibana_react.mdx +++ b/api_docs/kibana_react.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kibanaReact title: "kibanaReact" image: https://source.unsplash.com/400x175/?github description: API docs for the kibanaReact plugin -date: 2023-11-14 +date: 2023-11-16 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'kibanaReact'] --- import kibanaReactObj from './kibana_react.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 | |-------------------|-----------|------------------------|-----------------| -| 167 | 0 | 133 | 3 | +| 161 | 0 | 127 | 3 | ## Client diff --git a/api_docs/kibana_utils.mdx b/api_docs/kibana_utils.mdx index 6e697fb24ceea..ca28b725ddd7e 100644 --- a/api_docs/kibana_utils.mdx +++ b/api_docs/kibana_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kibanaUtils title: "kibanaUtils" image: https://source.unsplash.com/400x175/?github description: API docs for the kibanaUtils plugin -date: 2023-11-14 +date: 2023-11-16 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 7fefd2860d255..c95eecaf212b3 100644 --- a/api_docs/kubernetes_security.mdx +++ b/api_docs/kubernetes_security.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kubernetesSecurity title: "kubernetesSecurity" image: https://source.unsplash.com/400x175/?github description: API docs for the kubernetesSecurity plugin -date: 2023-11-14 +date: 2023-11-16 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'kubernetesSecurity'] --- import kubernetesSecurityObj from './kubernetes_security.devdocs.json'; diff --git a/api_docs/lens.devdocs.json b/api_docs/lens.devdocs.json index 74c9767733b92..0808aafa7726d 100644 --- a/api_docs/lens.devdocs.json +++ b/api_docs/lens.devdocs.json @@ -10650,7 +10650,7 @@ }, "<", "GoalDomainRange", - ">; base?: number | undefined; actual?: number | undefined; bandFillColor?: \"ignore\" | undefined; tickValueFormatter?: \"ignore\" | undefined; labelMajor?: string | ", + ">; actual?: number | undefined; base?: number | undefined; bandFillColor?: \"ignore\" | undefined; tickValueFormatter?: \"ignore\" | undefined; labelMajor?: string | ", "GoalLabelAccessor", " | undefined; labelMinor?: string | ", "GoalLabelAccessor", diff --git a/api_docs/lens.mdx b/api_docs/lens.mdx index 0b8052500697e..5f943d19e19c4 100644 --- a/api_docs/lens.mdx +++ b/api_docs/lens.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/lens title: "lens" image: https://source.unsplash.com/400x175/?github description: API docs for the lens plugin -date: 2023-11-14 +date: 2023-11-16 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 aabaea94f0684..0b78839bfd9cd 100644 --- a/api_docs/license_api_guard.mdx +++ b/api_docs/license_api_guard.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/licenseApiGuard title: "licenseApiGuard" image: https://source.unsplash.com/400x175/?github description: API docs for the licenseApiGuard plugin -date: 2023-11-14 +date: 2023-11-16 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 279e20dde497a..b15198d1460fa 100644 --- a/api_docs/license_management.mdx +++ b/api_docs/license_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/licenseManagement title: "licenseManagement" image: https://source.unsplash.com/400x175/?github description: API docs for the licenseManagement plugin -date: 2023-11-14 +date: 2023-11-16 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'licenseManagement'] --- import licenseManagementObj from './license_management.devdocs.json'; diff --git a/api_docs/licensing.devdocs.json b/api_docs/licensing.devdocs.json index 2d2924491b936..2fa21b35baeb7 100644 --- a/api_docs/licensing.devdocs.json +++ b/api_docs/licensing.devdocs.json @@ -2208,7 +2208,7 @@ }, { "plugin": "mapsEms", - "path": "src/plugins/maps_ems/server/index.ts" + "path": "src/plugins/maps_ems/server/plugin.ts" }, { "plugin": "osquery", @@ -2295,7 +2295,7 @@ "references": [ { "plugin": "mapsEms", - "path": "src/plugins/maps_ems/server/index.ts" + "path": "src/plugins/maps_ems/server/plugin.ts" } ], "children": [], diff --git a/api_docs/licensing.mdx b/api_docs/licensing.mdx index 99a12d51571ce..404178eee6f7f 100644 --- a/api_docs/licensing.mdx +++ b/api_docs/licensing.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/licensing title: "licensing" image: https://source.unsplash.com/400x175/?github description: API docs for the licensing plugin -date: 2023-11-14 +date: 2023-11-16 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 0d3170f6583e9..6fef3a10d5d64 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: 2023-11-14 +date: 2023-11-16 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 f62521671e3b3..44decb607a980 100644 --- a/api_docs/lists.mdx +++ b/api_docs/lists.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/lists title: "lists" image: https://source.unsplash.com/400x175/?github description: API docs for the lists plugin -date: 2023-11-14 +date: 2023-11-16 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'lists'] --- import listsObj from './lists.devdocs.json'; diff --git a/api_docs/log_explorer.mdx b/api_docs/log_explorer.mdx index c5e2d730a06fb..105ccbfe1bf51 100644 --- a/api_docs/log_explorer.mdx +++ b/api_docs/log_explorer.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/logExplorer title: "logExplorer" image: https://source.unsplash.com/400x175/?github description: API docs for the logExplorer plugin -date: 2023-11-14 +date: 2023-11-16 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'logExplorer'] --- import logExplorerObj from './log_explorer.devdocs.json'; diff --git a/api_docs/logs_shared.mdx b/api_docs/logs_shared.mdx index db8dd76259510..f84708561f3dd 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: 2023-11-14 +date: 2023-11-16 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 38de1040ff552..4715b32b3c07c 100644 --- a/api_docs/management.mdx +++ b/api_docs/management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/management title: "management" image: https://source.unsplash.com/400x175/?github description: API docs for the management plugin -date: 2023-11-14 +date: 2023-11-16 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'management'] --- import managementObj from './management.devdocs.json'; diff --git a/api_docs/maps.devdocs.json b/api_docs/maps.devdocs.json index b95d0314243be..56ef9cf8b744f 100644 --- a/api_docs/maps.devdocs.json +++ b/api_docs/maps.devdocs.json @@ -9,7 +9,7 @@ "tags": [], "label": "DataRequest", "description": [], - "path": "x-pack/plugins/maps/public/classes/util/data_request.ts", + "path": "x-pack/plugins/maps/public/classes/util/data_request.tsx", "deprecated": false, "trackAdoption": false, "children": [ @@ -23,7 +23,7 @@ "signature": [ "any" ], - "path": "x-pack/plugins/maps/public/classes/util/data_request.ts", + "path": "x-pack/plugins/maps/public/classes/util/data_request.tsx", "deprecated": false, "trackAdoption": false, "children": [ @@ -37,7 +37,7 @@ "signature": [ "DataRequestDescriptor" ], - "path": "x-pack/plugins/maps/public/classes/util/data_request.ts", + "path": "x-pack/plugins/maps/public/classes/util/data_request.tsx", "deprecated": false, "trackAdoption": false, "isRequired": true @@ -55,7 +55,7 @@ "signature": [ "() => object | undefined" ], - "path": "x-pack/plugins/maps/public/classes/util/data_request.ts", + "path": "x-pack/plugins/maps/public/classes/util/data_request.tsx", "deprecated": false, "trackAdoption": false, "children": [], @@ -71,7 +71,7 @@ "signature": [ "() => boolean" ], - "path": "x-pack/plugins/maps/public/classes/util/data_request.ts", + "path": "x-pack/plugins/maps/public/classes/util/data_request.tsx", "deprecated": false, "trackAdoption": false, "children": [], @@ -88,7 +88,7 @@ "() => ", "DataRequestMeta" ], - "path": "x-pack/plugins/maps/public/classes/util/data_request.ts", + "path": "x-pack/plugins/maps/public/classes/util/data_request.tsx", "deprecated": false, "trackAdoption": false, "children": [], @@ -104,7 +104,7 @@ "signature": [ "() => boolean" ], - "path": "x-pack/plugins/maps/public/classes/util/data_request.ts", + "path": "x-pack/plugins/maps/public/classes/util/data_request.tsx", "deprecated": false, "trackAdoption": false, "children": [], @@ -120,7 +120,7 @@ "signature": [ "() => boolean" ], - "path": "x-pack/plugins/maps/public/classes/util/data_request.ts", + "path": "x-pack/plugins/maps/public/classes/util/data_request.tsx", "deprecated": false, "trackAdoption": false, "children": [], @@ -136,7 +136,7 @@ "signature": [ "() => string" ], - "path": "x-pack/plugins/maps/public/classes/util/data_request.ts", + "path": "x-pack/plugins/maps/public/classes/util/data_request.tsx", "deprecated": false, "trackAdoption": false, "children": [], @@ -152,7 +152,7 @@ "signature": [ "() => symbol | undefined" ], - "path": "x-pack/plugins/maps/public/classes/util/data_request.ts", + "path": "x-pack/plugins/maps/public/classes/util/data_request.tsx", "deprecated": false, "trackAdoption": false, "children": [], @@ -160,15 +160,15 @@ }, { "parentPluginId": "maps", - "id": "def-public.DataRequest.getError", + "id": "def-public.DataRequest.renderError", "type": "Function", "tags": [], - "label": "getError", + "label": "renderError", "description": [], "signature": [ - "() => string | undefined" + "() => React.ReactNode" ], - "path": "x-pack/plugins/maps/public/classes/util/data_request.ts", + "path": "x-pack/plugins/maps/public/classes/util/data_request.tsx", "deprecated": false, "trackAdoption": false, "children": [], diff --git a/api_docs/maps.mdx b/api_docs/maps.mdx index 626297b9a4ca7..62a9a54b192cc 100644 --- a/api_docs/maps.mdx +++ b/api_docs/maps.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/maps title: "maps" image: https://source.unsplash.com/400x175/?github description: API docs for the maps plugin -date: 2023-11-14 +date: 2023-11-16 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'maps'] --- import mapsObj from './maps.devdocs.json'; diff --git a/api_docs/maps_ems.devdocs.json b/api_docs/maps_ems.devdocs.json index 697a5dd4c1c2f..2c555e52a83bc 100644 --- a/api_docs/maps_ems.devdocs.json +++ b/api_docs/maps_ems.devdocs.json @@ -416,251 +416,65 @@ } ], "initialIsOpen": false - }, - { - "parentPluginId": "mapsEms", - "id": "def-server.MapsEmsPlugin", - "type": "Class", - "tags": [], - "label": "MapsEmsPlugin", - "description": [], - "signature": [ - { - "pluginId": "mapsEms", - "scope": "server", - "docId": "kibMapsEmsPluginApi", - "section": "def-server.MapsEmsPlugin", - "text": "MapsEmsPlugin" - }, - " implements ", - { - "pluginId": "@kbn/core-plugins-server", - "scope": "common", - "docId": "kibKbnCorePluginsServerPluginApi", - "section": "def-common.Plugin", - "text": "Plugin" - }, - "<", - { - "pluginId": "mapsEms", - "scope": "server", - "docId": "kibMapsEmsPluginApi", - "section": "def-server.MapsEmsPluginServerSetup", - "text": "MapsEmsPluginServerSetup" - }, - ", void, object, object>" - ], - "path": "src/plugins/maps_ems/server/index.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "mapsEms", - "id": "def-server.MapsEmsPlugin._initializerContext", - "type": "Object", - "tags": [], - "label": "_initializerContext", - "description": [], - "signature": [ - { - "pluginId": "@kbn/core-plugins-server", - "scope": "common", - "docId": "kibKbnCorePluginsServerPluginApi", - "section": "def-common.PluginInitializerContext", - "text": "PluginInitializerContext" - }, - "; }>; includeElasticMapsService: boolean; emsUrl: string; emsFileApiUrl: string; emsTileApiUrl: string; emsLandingPageUrl: string; emsFontLibraryUrl: string; emsTileLayerId: Readonly<{} & { dark: string; bright: string; desaturated: string; }>; }>>" - ], - "path": "src/plugins/maps_ems/server/index.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "mapsEms", - "id": "def-server.MapsEmsPlugin.Unnamed", - "type": "Function", - "tags": [], - "label": "Constructor", - "description": [], - "signature": [ - "any" - ], - "path": "src/plugins/maps_ems/server/index.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "mapsEms", - "id": "def-server.MapsEmsPlugin.Unnamed.$1", - "type": "Object", - "tags": [], - "label": "initializerContext", - "description": [], - "signature": [ - { - "pluginId": "@kbn/core-plugins-server", - "scope": "common", - "docId": "kibKbnCorePluginsServerPluginApi", - "section": "def-common.PluginInitializerContext", - "text": "PluginInitializerContext" - }, - "; }>; includeElasticMapsService: boolean; emsUrl: string; emsFileApiUrl: string; emsTileApiUrl: string; emsLandingPageUrl: string; emsFontLibraryUrl: string; emsTileLayerId: Readonly<{} & { dark: string; bright: string; desaturated: string; }>; }>>" - ], - "path": "src/plugins/maps_ems/server/index.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": true - } - ], - "returnComment": [] - }, - { - "parentPluginId": "mapsEms", - "id": "def-server.MapsEmsPlugin.setup", - "type": "Function", - "tags": [], - "label": "setup", - "description": [], - "signature": [ - "(core: ", - { - "pluginId": "@kbn/core-lifecycle-server", - "scope": "common", - "docId": "kibKbnCoreLifecycleServerPluginApi", - "section": "def-common.CoreSetup", - "text": "CoreSetup" - }, - ", plugins: MapsEmsSetupServerDependencies) => { config: Readonly<{} & { tilemap: Readonly<{ url?: string | undefined; } & { options: Readonly<{ default?: boolean | undefined; tileSize?: number | undefined; subdomains?: string[] | undefined; errorTileUrl?: string | undefined; tms?: boolean | undefined; reuseTiles?: boolean | undefined; bounds?: number[] | undefined; } & { attribution: string; minZoom: number; maxZoom: number; }>; }>; includeElasticMapsService: boolean; emsUrl: string; emsFileApiUrl: string; emsTileApiUrl: string; emsLandingPageUrl: string; emsFontLibraryUrl: string; emsTileLayerId: Readonly<{} & { dark: string; bright: string; desaturated: string; }>; }>; createEMSSettings: () => ", - { - "pluginId": "mapsEms", - "scope": "common", - "docId": "kibMapsEmsPluginApi", - "section": "def-common.EMSSettings", - "text": "EMSSettings" - }, - "; }" - ], - "path": "src/plugins/maps_ems/server/index.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "mapsEms", - "id": "def-server.MapsEmsPlugin.setup.$1", - "type": "Object", - "tags": [], - "label": "core", - "description": [], - "signature": [ - { - "pluginId": "@kbn/core-lifecycle-server", - "scope": "common", - "docId": "kibKbnCoreLifecycleServerPluginApi", - "section": "def-common.CoreSetup", - "text": "CoreSetup" - }, - "" - ], - "path": "src/plugins/maps_ems/server/index.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": true - }, - { - "parentPluginId": "mapsEms", - "id": "def-server.MapsEmsPlugin.setup.$2", - "type": "Object", - "tags": [], - "label": "plugins", - "description": [], - "signature": [ - "MapsEmsSetupServerDependencies" - ], - "path": "src/plugins/maps_ems/server/index.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": true - } - ], - "returnComment": [] - }, - { - "parentPluginId": "mapsEms", - "id": "def-server.MapsEmsPlugin.start", - "type": "Function", - "tags": [], - "label": "start", - "description": [], - "signature": [ - "() => void" - ], - "path": "src/plugins/maps_ems/server/index.ts", - "deprecated": false, - "trackAdoption": false, - "children": [], - "returnComment": [] - } - ], - "initialIsOpen": false } ], "functions": [], - "interfaces": [ - { - "parentPluginId": "mapsEms", - "id": "def-server.MapsEmsPluginServerSetup", - "type": "Interface", - "tags": [], - "label": "MapsEmsPluginServerSetup", - "description": [], - "path": "src/plugins/maps_ems/server/index.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "mapsEms", - "id": "def-server.MapsEmsPluginServerSetup.config", - "type": "Object", - "tags": [], - "label": "config", - "description": [], - "signature": [ - "{ readonly tilemap: Readonly<{ url?: string | undefined; } & { options: Readonly<{ default?: boolean | undefined; tileSize?: number | undefined; subdomains?: string[] | undefined; errorTileUrl?: string | undefined; tms?: boolean | undefined; reuseTiles?: boolean | undefined; bounds?: number[] | undefined; } & { attribution: string; minZoom: number; maxZoom: number; }>; }>; readonly includeElasticMapsService: boolean; readonly emsUrl: string; readonly emsFileApiUrl: string; readonly emsTileApiUrl: string; readonly emsLandingPageUrl: string; readonly emsFontLibraryUrl: string; readonly emsTileLayerId: Readonly<{} & { dark: string; bright: string; desaturated: string; }>; }" - ], - "path": "src/plugins/maps_ems/server/index.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "mapsEms", - "id": "def-server.MapsEmsPluginServerSetup.createEMSSettings", - "type": "Function", - "tags": [], - "label": "createEMSSettings", - "description": [], - "signature": [ - "() => ", - { - "pluginId": "mapsEms", - "scope": "common", - "docId": "kibMapsEmsPluginApi", - "section": "def-common.EMSSettings", - "text": "EMSSettings" - } - ], - "path": "src/plugins/maps_ems/server/index.ts", - "deprecated": false, - "trackAdoption": false, - "children": [], - "returnComment": [] - } - ], - "initialIsOpen": false - } - ], + "interfaces": [], "enums": [], "misc": [], - "objects": [] + "objects": [], + "setup": { + "parentPluginId": "mapsEms", + "id": "def-server.MapsEmsPluginServerSetup", + "type": "Interface", + "tags": [], + "label": "MapsEmsPluginServerSetup", + "description": [], + "path": "src/plugins/maps_ems/server/plugin.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "mapsEms", + "id": "def-server.MapsEmsPluginServerSetup.config", + "type": "Object", + "tags": [], + "label": "config", + "description": [], + "signature": [ + "{ readonly tilemap: Readonly<{ url?: string | undefined; } & { options: Readonly<{ default?: boolean | undefined; tileSize?: number | undefined; subdomains?: string[] | undefined; errorTileUrl?: string | undefined; tms?: boolean | undefined; reuseTiles?: boolean | undefined; bounds?: number[] | undefined; } & { attribution: string; minZoom: number; maxZoom: number; }>; }>; readonly includeElasticMapsService: boolean; readonly emsUrl: string; readonly emsFileApiUrl: string; readonly emsTileApiUrl: string; readonly emsLandingPageUrl: string; readonly emsFontLibraryUrl: string; readonly emsTileLayerId: Readonly<{} & { dark: string; bright: string; desaturated: string; }>; }" + ], + "path": "src/plugins/maps_ems/server/plugin.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "mapsEms", + "id": "def-server.MapsEmsPluginServerSetup.createEMSSettings", + "type": "Function", + "tags": [], + "label": "createEMSSettings", + "description": [], + "signature": [ + "() => ", + { + "pluginId": "mapsEms", + "scope": "common", + "docId": "kibMapsEmsPluginApi", + "section": "def-common.EMSSettings", + "text": "EMSSettings" + } + ], + "path": "src/plugins/maps_ems/server/plugin.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [] + } + ], + "lifecycle": "setup", + "initialIsOpen": true + } }, "common": { "classes": [ diff --git a/api_docs/maps_ems.mdx b/api_docs/maps_ems.mdx index ed4cd61aabe05..6abe3da16aadb 100644 --- a/api_docs/maps_ems.mdx +++ b/api_docs/maps_ems.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/mapsEms title: "mapsEms" image: https://source.unsplash.com/400x175/?github description: API docs for the mapsEms plugin -date: 2023-11-14 +date: 2023-11-16 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'mapsEms'] --- import mapsEmsObj from './maps_ems.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/kibana-gis](https://github.com/orgs/elastic/teams/kibana-gis) | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 68 | 0 | 68 | 0 | +| 60 | 0 | 60 | 0 | ## Client @@ -39,12 +39,12 @@ Contact [@elastic/kibana-gis](https://github.com/orgs/elastic/teams/kibana-gis) ## Server +### Setup + + ### Classes -### Interfaces - - ## Common ### Classes diff --git a/api_docs/metrics_data_access.mdx b/api_docs/metrics_data_access.mdx index a9aa6174f9a8d..95b7422071971 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: 2023-11-14 +date: 2023-11-16 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 b148f1f2fa501..c1ad326590a83 100644 --- a/api_docs/ml.mdx +++ b/api_docs/ml.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/ml title: "ml" image: https://source.unsplash.com/400x175/?github description: API docs for the ml plugin -date: 2023-11-14 +date: 2023-11-16 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'ml'] --- import mlObj from './ml.devdocs.json'; diff --git a/api_docs/monitoring.mdx b/api_docs/monitoring.mdx index 0d94c036ada02..4b2a335daee9c 100644 --- a/api_docs/monitoring.mdx +++ b/api_docs/monitoring.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/monitoring title: "monitoring" image: https://source.unsplash.com/400x175/?github description: API docs for the monitoring plugin -date: 2023-11-14 +date: 2023-11-16 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 4eddd6df47a06..14d4b44e3f520 100644 --- a/api_docs/monitoring_collection.mdx +++ b/api_docs/monitoring_collection.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/monitoringCollection title: "monitoringCollection" image: https://source.unsplash.com/400x175/?github description: API docs for the monitoringCollection plugin -date: 2023-11-14 +date: 2023-11-16 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 405d3e301c581..8e5fe7c5e044d 100644 --- a/api_docs/navigation.mdx +++ b/api_docs/navigation.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/navigation title: "navigation" image: https://source.unsplash.com/400x175/?github description: API docs for the navigation plugin -date: 2023-11-14 +date: 2023-11-16 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 e68e301c181ab..3af33a3c7facd 100644 --- a/api_docs/newsfeed.mdx +++ b/api_docs/newsfeed.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/newsfeed title: "newsfeed" image: https://source.unsplash.com/400x175/?github description: API docs for the newsfeed plugin -date: 2023-11-14 +date: 2023-11-16 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 4fcd5ff737806..81ef92527b9f4 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: 2023-11-14 +date: 2023-11-16 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 5f7b1e4fed9fa..d46bcbbda45c6 100644 --- a/api_docs/notifications.mdx +++ b/api_docs/notifications.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/notifications title: "notifications" image: https://source.unsplash.com/400x175/?github description: API docs for the notifications plugin -date: 2023-11-14 +date: 2023-11-16 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 0610ed9ace5c9..f0d4f0c019ba5 100644 --- a/api_docs/observability.devdocs.json +++ b/api_docs/observability.devdocs.json @@ -3339,7 +3339,7 @@ "label": "format", "description": [], "signature": [ - "(options: { fields: OutputOf> & Record; formatters: { asDuration: (value: ", + "(options: { fields: OutputOf> & Record; formatters: { asDuration: (value: ", "Maybe", ", { defaultValue, extended }?: FormatterOptions) => string; asPercent: (numerator: ", "Maybe", @@ -3358,7 +3358,7 @@ "label": "options", "description": [], "signature": [ - "{ fields: OutputOf> & Record; formatters: { asDuration: (value: ", + "{ fields: OutputOf> & Record; formatters: { asDuration: (value: ", "Maybe", ", { defaultValue, extended }?: FormatterOptions) => string; asPercent: (numerator: ", "Maybe", @@ -3566,7 +3566,7 @@ "label": "fields", "description": [], "signature": [ - "OutputOf> & OutputOf> & TAdditionalMetaFields" + "OutputOf> & OutputOf> & TAdditionalMetaFields" ], "path": "x-pack/plugins/observability/public/typings/alerts.ts", "deprecated": false, @@ -4366,7 +4366,7 @@ "label": "ObservabilityRuleTypeFormatter", "description": [], "signature": [ - "(options: { fields: OutputOf> & Record; formatters: { asDuration: (value: ", + "(options: { fields: OutputOf> & Record; formatters: { asDuration: (value: ", "Maybe", ", { defaultValue, extended }?: FormatterOptions) => string; asPercent: (numerator: ", "Maybe", @@ -4385,7 +4385,7 @@ "label": "options", "description": [], "signature": [ - "{ fields: OutputOf> & Record; formatters: { asDuration: (value: ", + "{ fields: OutputOf> & Record; formatters: { asDuration: (value: ", "Maybe", ", { defaultValue, extended }?: FormatterOptions) => string; asPercent: (numerator: ", "Maybe", @@ -8156,7 +8156,29 @@ "label": "ObservabilityAPIReturnType", "description": [], "signature": [ - "{ \"GET /internal/observability/slos/{id}/_instances\": { endpoint: \"GET /internal/observability/slos/{id}/_instances\"; params?: ", + "{ \"POST /api/observability/slos/{id}/_reset 2023-10-31\": { endpoint: \"POST /api/observability/slos/{id}/_reset 2023-10-31\"; params?: ", + "TypeC", + "<{ path: ", + "TypeC", + "<{ id: ", + "StringC", + "; }>; }> | undefined; handler: ({}: ", + { + "pluginId": "observability", + "scope": "server", + "docId": "kibObservabilityPluginApi", + "section": "def-server.ObservabilityRouteHandlerResources", + "text": "ObservabilityRouteHandlerResources" + }, + " & { params: { path: { id: string; }; }; }) => Promise<{ 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 | undefined; }; } | { type: \"sli.apm.transactionErrorRate\"; params: { environment: string; service: string; transactionType: string; transactionName: string; index: string; } & { filter?: string | undefined; }; } | { type: \"sli.kql.custom\"; params: { index: string; good: string; total: string; timestampField: string; } & { filter?: string | undefined; }; } | { type: \"sli.metric.custom\"; params: { index: string; good: { metrics: (({ name: string; aggregation: \"sum\"; field: string; } & { filter?: string | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: string | undefined; }))[]; equation: string; }; total: { metrics: (({ name: string; aggregation: \"sum\"; field: string; } & { filter?: string | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: string | undefined; }))[]; equation: string; }; timestampField: string; } & { filter?: string | undefined; }; } | { type: \"sli.metric.timeslice\"; params: { index: string; metric: { metrics: (({ name: string; aggregation: \"min\" | \"max\" | \"sum\" | \"avg\" | \"cardinality\" | \"last_value\" | \"std_deviation\"; field: string; } & { filter?: string | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: string | undefined; }) | ({ name: string; aggregation: \"percentile\"; field: string; percentile: number; } & { filter?: string | undefined; }))[]; equation: string; threshold: number; comparator: \"GT\" | \"GTE\" | \"LT\" | \"LTE\"; }; timestampField: string; } & { filter?: string | undefined; }; } | { type: \"sli.histogram.custom\"; params: { index: string; timestampField: string; good: ({ field: string; aggregation: \"value_count\"; } & { filter?: string | undefined; }) | ({ field: string; aggregation: \"range\"; from: number; to: number; } & { filter?: string | undefined; }); total: ({ field: string; aggregation: \"value_count\"; } & { filter?: string | undefined; }) | ({ field: string; aggregation: \"range\"; from: number; to: number; } & { filter?: string | undefined; }); } & { filter?: string | undefined; }; }; timeWindow: { duration: string; type: \"rolling\"; } | { duration: string; type: \"calendarAligned\"; }; budgetingMethod: \"occurrences\" | \"timeslices\"; objective: { target: number; } & { timesliceTarget?: number | undefined; timesliceWindow?: string | undefined; }; revision: number; settings: { syncDelay: string; frequency: string; }; enabled: boolean; tags: string[]; groupBy: string; createdAt: string; updatedAt: string; version: number; } & { instanceId?: string | undefined; }>; } & ", + { + "pluginId": "observability", + "scope": "server", + "docId": "kibObservabilityPluginApi", + "section": "def-server.ObservabilityRouteCreateOptions", + "text": "ObservabilityRouteCreateOptions" + }, + "; \"GET /internal/observability/slos/{id}/_instances\": { endpoint: \"GET /internal/observability/slos/{id}/_instances\"; params?: ", "TypeC", "<{ path: ", "TypeC", @@ -9082,7 +9104,7 @@ "section": "def-common.Duration", "text": "Duration" }, - " | undefined; } | undefined; tags?: string[] | undefined; groupBy?: string | undefined; }; }; }) => Promise<{ 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 | undefined; }; } | { type: \"sli.apm.transactionErrorRate\"; params: { environment: string; service: string; transactionType: string; transactionName: string; index: string; } & { filter?: string | undefined; }; } | { type: \"sli.kql.custom\"; params: { index: string; good: string; total: string; timestampField: string; } & { filter?: string | undefined; }; } | { type: \"sli.metric.custom\"; params: { index: string; good: { metrics: (({ name: string; aggregation: \"sum\"; field: string; } & { filter?: string | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: string | undefined; }))[]; equation: string; }; total: { metrics: (({ name: string; aggregation: \"sum\"; field: string; } & { filter?: string | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: string | undefined; }))[]; equation: string; }; timestampField: string; } & { filter?: string | undefined; }; } | { type: \"sli.metric.timeslice\"; params: { index: string; metric: { metrics: (({ name: string; aggregation: \"min\" | \"max\" | \"sum\" | \"avg\" | \"cardinality\" | \"last_value\" | \"std_deviation\"; field: string; } & { filter?: string | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: string | undefined; }) | ({ name: string; aggregation: \"percentile\"; field: string; percentile: number; } & { filter?: string | undefined; }))[]; equation: string; threshold: number; comparator: \"GT\" | \"GTE\" | \"LT\" | \"LTE\"; }; timestampField: string; } & { filter?: string | undefined; }; } | { type: \"sli.histogram.custom\"; params: { index: string; timestampField: string; good: ({ field: string; aggregation: \"value_count\"; } & { filter?: string | undefined; }) | ({ field: string; aggregation: \"range\"; from: number; to: number; } & { filter?: string | undefined; }); total: ({ field: string; aggregation: \"value_count\"; } & { filter?: string | undefined; }) | ({ field: string; aggregation: \"range\"; from: number; to: number; } & { filter?: string | undefined; }); } & { filter?: string | undefined; }; }; timeWindow: { duration: string; type: \"rolling\"; } | { duration: string; type: \"calendarAligned\"; }; budgetingMethod: \"occurrences\" | \"timeslices\"; objective: { target: number; } & { timesliceTarget?: number | undefined; timesliceWindow?: string | undefined; }; revision: number; settings: { syncDelay: string; frequency: string; }; enabled: boolean; tags: string[]; groupBy: string; createdAt: string; updatedAt: string; } & { instanceId?: string | undefined; }>; } & ", + " | undefined; } | undefined; tags?: string[] | undefined; groupBy?: string | undefined; }; }; }) => Promise<{ 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 | undefined; }; } | { type: \"sli.apm.transactionErrorRate\"; params: { environment: string; service: string; transactionType: string; transactionName: string; index: string; } & { filter?: string | undefined; }; } | { type: \"sli.kql.custom\"; params: { index: string; good: string; total: string; timestampField: string; } & { filter?: string | undefined; }; } | { type: \"sli.metric.custom\"; params: { index: string; good: { metrics: (({ name: string; aggregation: \"sum\"; field: string; } & { filter?: string | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: string | undefined; }))[]; equation: string; }; total: { metrics: (({ name: string; aggregation: \"sum\"; field: string; } & { filter?: string | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: string | undefined; }))[]; equation: string; }; timestampField: string; } & { filter?: string | undefined; }; } | { type: \"sli.metric.timeslice\"; params: { index: string; metric: { metrics: (({ name: string; aggregation: \"min\" | \"max\" | \"sum\" | \"avg\" | \"cardinality\" | \"last_value\" | \"std_deviation\"; field: string; } & { filter?: string | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: string | undefined; }) | ({ name: string; aggregation: \"percentile\"; field: string; percentile: number; } & { filter?: string | undefined; }))[]; equation: string; threshold: number; comparator: \"GT\" | \"GTE\" | \"LT\" | \"LTE\"; }; timestampField: string; } & { filter?: string | undefined; }; } | { type: \"sli.histogram.custom\"; params: { index: string; timestampField: string; good: ({ field: string; aggregation: \"value_count\"; } & { filter?: string | undefined; }) | ({ field: string; aggregation: \"range\"; from: number; to: number; } & { filter?: string | undefined; }); total: ({ field: string; aggregation: \"value_count\"; } & { filter?: string | undefined; }) | ({ field: string; aggregation: \"range\"; from: number; to: number; } & { filter?: string | undefined; }); } & { filter?: string | undefined; }; }; timeWindow: { duration: string; type: \"rolling\"; } | { duration: string; type: \"calendarAligned\"; }; budgetingMethod: \"occurrences\" | \"timeslices\"; objective: { target: number; } & { timesliceTarget?: number | undefined; timesliceWindow?: string | undefined; }; revision: number; settings: { syncDelay: string; frequency: string; }; enabled: boolean; tags: string[]; groupBy: string; createdAt: string; updatedAt: string; version: number; } & { instanceId?: string | undefined; }>; } & ", { "pluginId": "observability", "scope": "server", @@ -9116,7 +9138,7 @@ "section": "def-server.ObservabilityRouteHandlerResources", "text": "ObservabilityRouteHandlerResources" }, - " & { params: { path: { id: string; }; } & { query?: { instanceId?: string | undefined; } | undefined; }; }) => Promise<{ 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 | undefined; }; } | { type: \"sli.apm.transactionErrorRate\"; params: { environment: string; service: string; transactionType: string; transactionName: string; index: string; } & { filter?: string | undefined; }; } | { type: \"sli.kql.custom\"; params: { index: string; good: string; total: string; timestampField: string; } & { filter?: string | undefined; }; } | { type: \"sli.metric.custom\"; params: { index: string; good: { metrics: (({ name: string; aggregation: \"sum\"; field: string; } & { filter?: string | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: string | undefined; }))[]; equation: string; }; total: { metrics: (({ name: string; aggregation: \"sum\"; field: string; } & { filter?: string | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: string | undefined; }))[]; equation: string; }; timestampField: string; } & { filter?: string | undefined; }; } | { type: \"sli.metric.timeslice\"; params: { index: string; metric: { metrics: (({ name: string; aggregation: \"min\" | \"max\" | \"sum\" | \"avg\" | \"cardinality\" | \"last_value\" | \"std_deviation\"; field: string; } & { filter?: string | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: string | undefined; }) | ({ name: string; aggregation: \"percentile\"; field: string; percentile: number; } & { filter?: string | undefined; }))[]; equation: string; threshold: number; comparator: \"GT\" | \"GTE\" | \"LT\" | \"LTE\"; }; timestampField: string; } & { filter?: string | undefined; }; } | { type: \"sli.histogram.custom\"; params: { index: string; timestampField: string; good: ({ field: string; aggregation: \"value_count\"; } & { filter?: string | undefined; }) | ({ field: string; aggregation: \"range\"; from: number; to: number; } & { filter?: string | undefined; }); total: ({ field: string; aggregation: \"value_count\"; } & { filter?: string | undefined; }) | ({ field: string; aggregation: \"range\"; from: number; to: number; } & { filter?: string | undefined; }); } & { filter?: string | undefined; }; }; timeWindow: { duration: string; type: \"rolling\"; } | { duration: string; type: \"calendarAligned\"; }; budgetingMethod: \"occurrences\" | \"timeslices\"; objective: { target: number; } & { timesliceTarget?: number | undefined; timesliceWindow?: string | undefined; }; revision: number; settings: { syncDelay: string; frequency: string; }; enabled: boolean; tags: string[]; groupBy: string; createdAt: string; updatedAt: string; } & { instanceId?: string | undefined; } & { summary: { status: \"HEALTHY\" | \"NO_DATA\" | \"DEGRADING\" | \"VIOLATED\"; sliValue: number; errorBudget: { initial: number; consumed: number; remaining: number; isEstimated: boolean; }; }; }>; } & ", + " & { params: { path: { id: string; }; } & { query?: { instanceId?: string | undefined; } | undefined; }; }) => Promise<{ 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 | undefined; }; } | { type: \"sli.apm.transactionErrorRate\"; params: { environment: string; service: string; transactionType: string; transactionName: string; index: string; } & { filter?: string | undefined; }; } | { type: \"sli.kql.custom\"; params: { index: string; good: string; total: string; timestampField: string; } & { filter?: string | undefined; }; } | { type: \"sli.metric.custom\"; params: { index: string; good: { metrics: (({ name: string; aggregation: \"sum\"; field: string; } & { filter?: string | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: string | undefined; }))[]; equation: string; }; total: { metrics: (({ name: string; aggregation: \"sum\"; field: string; } & { filter?: string | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: string | undefined; }))[]; equation: string; }; timestampField: string; } & { filter?: string | undefined; }; } | { type: \"sli.metric.timeslice\"; params: { index: string; metric: { metrics: (({ name: string; aggregation: \"min\" | \"max\" | \"sum\" | \"avg\" | \"cardinality\" | \"last_value\" | \"std_deviation\"; field: string; } & { filter?: string | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: string | undefined; }) | ({ name: string; aggregation: \"percentile\"; field: string; percentile: number; } & { filter?: string | undefined; }))[]; equation: string; threshold: number; comparator: \"GT\" | \"GTE\" | \"LT\" | \"LTE\"; }; timestampField: string; } & { filter?: string | undefined; }; } | { type: \"sli.histogram.custom\"; params: { index: string; timestampField: string; good: ({ field: string; aggregation: \"value_count\"; } & { filter?: string | undefined; }) | ({ field: string; aggregation: \"range\"; from: number; to: number; } & { filter?: string | undefined; }); total: ({ field: string; aggregation: \"value_count\"; } & { filter?: string | undefined; }) | ({ field: string; aggregation: \"range\"; from: number; to: number; } & { filter?: string | undefined; }); } & { filter?: string | undefined; }; }; timeWindow: { duration: string; type: \"rolling\"; } | { duration: string; type: \"calendarAligned\"; }; budgetingMethod: \"occurrences\" | \"timeslices\"; objective: { target: number; } & { timesliceTarget?: number | undefined; timesliceWindow?: string | undefined; }; revision: number; settings: { syncDelay: string; frequency: string; }; enabled: boolean; tags: string[]; groupBy: string; createdAt: string; updatedAt: string; version: number; } & { instanceId?: string | undefined; } & { summary: { status: \"HEALTHY\" | \"NO_DATA\" | \"DEGRADING\" | \"VIOLATED\"; sliValue: number; errorBudget: { initial: number; consumed: number; remaining: number; isEstimated: boolean; }; }; }>; } & ", { "pluginId": "observability", "scope": "server", @@ -9158,7 +9180,7 @@ "section": "def-server.ObservabilityRouteHandlerResources", "text": "ObservabilityRouteHandlerResources" }, - " & { params?: { query?: { kqlQuery?: string | undefined; page?: string | undefined; perPage?: string | undefined; sortBy?: \"status\" | \"error_budget_consumed\" | \"error_budget_remaining\" | \"sli_value\" | undefined; sortDirection?: \"asc\" | \"desc\" | undefined; } | undefined; } | undefined; }) => Promise<{ 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 | undefined; }; } | { type: \"sli.apm.transactionErrorRate\"; params: { environment: string; service: string; transactionType: string; transactionName: string; index: string; } & { filter?: string | undefined; }; } | { type: \"sli.kql.custom\"; params: { index: string; good: string; total: string; timestampField: string; } & { filter?: string | undefined; }; } | { type: \"sli.metric.custom\"; params: { index: string; good: { metrics: (({ name: string; aggregation: \"sum\"; field: string; } & { filter?: string | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: string | undefined; }))[]; equation: string; }; total: { metrics: (({ name: string; aggregation: \"sum\"; field: string; } & { filter?: string | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: string | undefined; }))[]; equation: string; }; timestampField: string; } & { filter?: string | undefined; }; } | { type: \"sli.metric.timeslice\"; params: { index: string; metric: { metrics: (({ name: string; aggregation: \"min\" | \"max\" | \"sum\" | \"avg\" | \"cardinality\" | \"last_value\" | \"std_deviation\"; field: string; } & { filter?: string | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: string | undefined; }) | ({ name: string; aggregation: \"percentile\"; field: string; percentile: number; } & { filter?: string | undefined; }))[]; equation: string; threshold: number; comparator: \"GT\" | \"GTE\" | \"LT\" | \"LTE\"; }; timestampField: string; } & { filter?: string | undefined; }; } | { type: \"sli.histogram.custom\"; params: { index: string; timestampField: string; good: ({ field: string; aggregation: \"value_count\"; } & { filter?: string | undefined; }) | ({ field: string; aggregation: \"range\"; from: number; to: number; } & { filter?: string | undefined; }); total: ({ field: string; aggregation: \"value_count\"; } & { filter?: string | undefined; }) | ({ field: string; aggregation: \"range\"; from: number; to: number; } & { filter?: string | undefined; }); } & { filter?: string | undefined; }; }; timeWindow: { duration: string; type: \"rolling\"; } | { duration: string; type: \"calendarAligned\"; }; budgetingMethod: \"occurrences\" | \"timeslices\"; objective: { target: number; } & { timesliceTarget?: number | undefined; timesliceWindow?: string | undefined; }; revision: number; settings: { syncDelay: string; frequency: string; }; enabled: boolean; tags: string[]; groupBy: string; createdAt: string; updatedAt: string; } & { instanceId?: string | undefined; } & { summary: { status: \"HEALTHY\" | \"NO_DATA\" | \"DEGRADING\" | \"VIOLATED\"; sliValue: number; errorBudget: { initial: number; consumed: number; remaining: number; isEstimated: boolean; }; }; })[]; }>; } & ", + " & { params?: { query?: { kqlQuery?: string | undefined; page?: string | undefined; perPage?: string | undefined; sortBy?: \"status\" | \"error_budget_consumed\" | \"error_budget_remaining\" | \"sli_value\" | undefined; sortDirection?: \"asc\" | \"desc\" | undefined; } | undefined; } | undefined; }) => Promise<{ 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 | undefined; }; } | { type: \"sli.apm.transactionErrorRate\"; params: { environment: string; service: string; transactionType: string; transactionName: string; index: string; } & { filter?: string | undefined; }; } | { type: \"sli.kql.custom\"; params: { index: string; good: string; total: string; timestampField: string; } & { filter?: string | undefined; }; } | { type: \"sli.metric.custom\"; params: { index: string; good: { metrics: (({ name: string; aggregation: \"sum\"; field: string; } & { filter?: string | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: string | undefined; }))[]; equation: string; }; total: { metrics: (({ name: string; aggregation: \"sum\"; field: string; } & { filter?: string | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: string | undefined; }))[]; equation: string; }; timestampField: string; } & { filter?: string | undefined; }; } | { type: \"sli.metric.timeslice\"; params: { index: string; metric: { metrics: (({ name: string; aggregation: \"min\" | \"max\" | \"sum\" | \"avg\" | \"cardinality\" | \"last_value\" | \"std_deviation\"; field: string; } & { filter?: string | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: string | undefined; }) | ({ name: string; aggregation: \"percentile\"; field: string; percentile: number; } & { filter?: string | undefined; }))[]; equation: string; threshold: number; comparator: \"GT\" | \"GTE\" | \"LT\" | \"LTE\"; }; timestampField: string; } & { filter?: string | undefined; }; } | { type: \"sli.histogram.custom\"; params: { index: string; timestampField: string; good: ({ field: string; aggregation: \"value_count\"; } & { filter?: string | undefined; }) | ({ field: string; aggregation: \"range\"; from: number; to: number; } & { filter?: string | undefined; }); total: ({ field: string; aggregation: \"value_count\"; } & { filter?: string | undefined; }) | ({ field: string; aggregation: \"range\"; from: number; to: number; } & { filter?: string | undefined; }); } & { filter?: string | undefined; }; }; timeWindow: { duration: string; type: \"rolling\"; } | { duration: string; type: \"calendarAligned\"; }; budgetingMethod: \"occurrences\" | \"timeslices\"; objective: { target: number; } & { timesliceTarget?: number | undefined; timesliceWindow?: string | undefined; }; revision: number; settings: { syncDelay: string; frequency: string; }; enabled: boolean; tags: string[]; groupBy: string; createdAt: string; updatedAt: string; version: number; } & { instanceId?: string | undefined; } & { summary: { status: \"HEALTHY\" | \"NO_DATA\" | \"DEGRADING\" | \"VIOLATED\"; sliValue: number; errorBudget: { initial: number; consumed: number; remaining: number; isEstimated: boolean; }; }; })[]; }>; } & ", { "pluginId": "observability", "scope": "server", @@ -9166,12 +9188,18 @@ "section": "def-server.ObservabilityRouteCreateOptions", "text": "ObservabilityRouteCreateOptions" }, - "; \"GET /internal/observability/slos/_definitions\": { endpoint: \"GET /internal/observability/slos/_definitions\"; params?: ", - "TypeC", + "; \"GET /api/observability/slos/_definitions 2023-10-31\": { endpoint: \"GET /api/observability/slos/_definitions 2023-10-31\"; params?: ", + "PartialC", "<{ query: ", - "TypeC", + "PartialC", "<{ search: ", "StringC", + "; includeOutdatedOnly: ", + "Type", + "; page: ", + "StringC", + "; perPage: ", + "StringC", "; }>; }> | undefined; handler: ({}: ", { "pluginId": "observability", @@ -9180,7 +9208,7 @@ "section": "def-server.ObservabilityRouteHandlerResources", "text": "ObservabilityRouteHandlerResources" }, - " & { params: { query: { search: string; }; }; }) => Promise<({ 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 | undefined; }; } | { type: \"sli.apm.transactionErrorRate\"; params: { environment: string; service: string; transactionType: string; transactionName: string; index: string; } & { filter?: string | undefined; }; } | { type: \"sli.kql.custom\"; params: { index: string; good: string; total: string; timestampField: string; } & { filter?: string | undefined; }; } | { type: \"sli.metric.custom\"; params: { index: string; good: { metrics: (({ name: string; aggregation: \"sum\"; field: string; } & { filter?: string | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: string | undefined; }))[]; equation: string; }; total: { metrics: (({ name: string; aggregation: \"sum\"; field: string; } & { filter?: string | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: string | undefined; }))[]; equation: string; }; timestampField: string; } & { filter?: string | undefined; }; } | { type: \"sli.metric.timeslice\"; params: { index: string; metric: { metrics: (({ name: string; aggregation: \"min\" | \"max\" | \"sum\" | \"avg\" | \"cardinality\" | \"last_value\" | \"std_deviation\"; field: string; } & { filter?: string | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: string | undefined; }) | ({ name: string; aggregation: \"percentile\"; field: string; percentile: number; } & { filter?: string | undefined; }))[]; equation: string; threshold: number; comparator: \"GT\" | \"GTE\" | \"LT\" | \"LTE\"; }; timestampField: string; } & { filter?: string | undefined; }; } | { type: \"sli.histogram.custom\"; params: { index: string; timestampField: string; good: ({ field: string; aggregation: \"value_count\"; } & { filter?: string | undefined; }) | ({ field: string; aggregation: \"range\"; from: number; to: number; } & { filter?: string | undefined; }); total: ({ field: string; aggregation: \"value_count\"; } & { filter?: string | undefined; }) | ({ field: string; aggregation: \"range\"; from: number; to: number; } & { filter?: string | undefined; }); } & { filter?: string | undefined; }; }; timeWindow: { duration: string; type: \"rolling\"; } | { duration: string; type: \"calendarAligned\"; }; budgetingMethod: \"occurrences\" | \"timeslices\"; objective: { target: number; } & { timesliceTarget?: number | undefined; timesliceWindow?: string | undefined; }; revision: number; settings: { syncDelay: string; frequency: string; }; enabled: boolean; tags: string[]; groupBy: string; createdAt: string; updatedAt: string; } & { instanceId?: string | undefined; })[]>; } & ", + " & { params?: { query?: { search?: string | undefined; includeOutdatedOnly?: boolean | undefined; page?: string | undefined; perPage?: string | undefined; } | undefined; } | undefined; }) => Promise<{ 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 | undefined; }; } | { type: \"sli.apm.transactionErrorRate\"; params: { environment: string; service: string; transactionType: string; transactionName: string; index: string; } & { filter?: string | undefined; }; } | { type: \"sli.kql.custom\"; params: { index: string; good: string; total: string; timestampField: string; } & { filter?: string | undefined; }; } | { type: \"sli.metric.custom\"; params: { index: string; good: { metrics: (({ name: string; aggregation: \"sum\"; field: string; } & { filter?: string | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: string | undefined; }))[]; equation: string; }; total: { metrics: (({ name: string; aggregation: \"sum\"; field: string; } & { filter?: string | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: string | undefined; }))[]; equation: string; }; timestampField: string; } & { filter?: string | undefined; }; } | { type: \"sli.metric.timeslice\"; params: { index: string; metric: { metrics: (({ name: string; aggregation: \"min\" | \"max\" | \"sum\" | \"avg\" | \"cardinality\" | \"last_value\" | \"std_deviation\"; field: string; } & { filter?: string | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: string | undefined; }) | ({ name: string; aggregation: \"percentile\"; field: string; percentile: number; } & { filter?: string | undefined; }))[]; equation: string; threshold: number; comparator: \"GT\" | \"GTE\" | \"LT\" | \"LTE\"; }; timestampField: string; } & { filter?: string | undefined; }; } | { type: \"sli.histogram.custom\"; params: { index: string; timestampField: string; good: ({ field: string; aggregation: \"value_count\"; } & { filter?: string | undefined; }) | ({ field: string; aggregation: \"range\"; from: number; to: number; } & { filter?: string | undefined; }); total: ({ field: string; aggregation: \"value_count\"; } & { filter?: string | undefined; }) | ({ field: string; aggregation: \"range\"; from: number; to: number; } & { filter?: string | undefined; }); } & { filter?: string | undefined; }; }; timeWindow: { duration: string; type: \"rolling\"; } | { duration: string; type: \"calendarAligned\"; }; budgetingMethod: \"occurrences\" | \"timeslices\"; objective: { target: number; } & { timesliceTarget?: number | undefined; timesliceWindow?: string | undefined; }; revision: number; settings: { syncDelay: string; frequency: string; }; enabled: boolean; tags: string[]; groupBy: string; createdAt: string; updatedAt: string; version: number; } & { instanceId?: string | undefined; })[]; }>; } & ", { "pluginId": "observability", "scope": "server", @@ -9860,7 +9888,29 @@ "label": "ObservabilityServerRouteRepository", "description": [], "signature": [ - "{ \"GET /internal/observability/slos/{id}/_instances\": { endpoint: \"GET /internal/observability/slos/{id}/_instances\"; params?: ", + "{ \"POST /api/observability/slos/{id}/_reset 2023-10-31\": { endpoint: \"POST /api/observability/slos/{id}/_reset 2023-10-31\"; params?: ", + "TypeC", + "<{ path: ", + "TypeC", + "<{ id: ", + "StringC", + "; }>; }> | undefined; handler: ({}: ", + { + "pluginId": "observability", + "scope": "server", + "docId": "kibObservabilityPluginApi", + "section": "def-server.ObservabilityRouteHandlerResources", + "text": "ObservabilityRouteHandlerResources" + }, + " & { params: { path: { id: string; }; }; }) => Promise<{ 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 | undefined; }; } | { type: \"sli.apm.transactionErrorRate\"; params: { environment: string; service: string; transactionType: string; transactionName: string; index: string; } & { filter?: string | undefined; }; } | { type: \"sli.kql.custom\"; params: { index: string; good: string; total: string; timestampField: string; } & { filter?: string | undefined; }; } | { type: \"sli.metric.custom\"; params: { index: string; good: { metrics: (({ name: string; aggregation: \"sum\"; field: string; } & { filter?: string | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: string | undefined; }))[]; equation: string; }; total: { metrics: (({ name: string; aggregation: \"sum\"; field: string; } & { filter?: string | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: string | undefined; }))[]; equation: string; }; timestampField: string; } & { filter?: string | undefined; }; } | { type: \"sli.metric.timeslice\"; params: { index: string; metric: { metrics: (({ name: string; aggregation: \"min\" | \"max\" | \"sum\" | \"avg\" | \"cardinality\" | \"last_value\" | \"std_deviation\"; field: string; } & { filter?: string | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: string | undefined; }) | ({ name: string; aggregation: \"percentile\"; field: string; percentile: number; } & { filter?: string | undefined; }))[]; equation: string; threshold: number; comparator: \"GT\" | \"GTE\" | \"LT\" | \"LTE\"; }; timestampField: string; } & { filter?: string | undefined; }; } | { type: \"sli.histogram.custom\"; params: { index: string; timestampField: string; good: ({ field: string; aggregation: \"value_count\"; } & { filter?: string | undefined; }) | ({ field: string; aggregation: \"range\"; from: number; to: number; } & { filter?: string | undefined; }); total: ({ field: string; aggregation: \"value_count\"; } & { filter?: string | undefined; }) | ({ field: string; aggregation: \"range\"; from: number; to: number; } & { filter?: string | undefined; }); } & { filter?: string | undefined; }; }; timeWindow: { duration: string; type: \"rolling\"; } | { duration: string; type: \"calendarAligned\"; }; budgetingMethod: \"occurrences\" | \"timeslices\"; objective: { target: number; } & { timesliceTarget?: number | undefined; timesliceWindow?: string | undefined; }; revision: number; settings: { syncDelay: string; frequency: string; }; enabled: boolean; tags: string[]; groupBy: string; createdAt: string; updatedAt: string; version: number; } & { instanceId?: string | undefined; }>; } & ", + { + "pluginId": "observability", + "scope": "server", + "docId": "kibObservabilityPluginApi", + "section": "def-server.ObservabilityRouteCreateOptions", + "text": "ObservabilityRouteCreateOptions" + }, + "; \"GET /internal/observability/slos/{id}/_instances\": { endpoint: \"GET /internal/observability/slos/{id}/_instances\"; params?: ", "TypeC", "<{ path: ", "TypeC", @@ -10786,7 +10836,7 @@ "section": "def-common.Duration", "text": "Duration" }, - " | undefined; } | undefined; tags?: string[] | undefined; groupBy?: string | undefined; }; }; }) => Promise<{ 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 | undefined; }; } | { type: \"sli.apm.transactionErrorRate\"; params: { environment: string; service: string; transactionType: string; transactionName: string; index: string; } & { filter?: string | undefined; }; } | { type: \"sli.kql.custom\"; params: { index: string; good: string; total: string; timestampField: string; } & { filter?: string | undefined; }; } | { type: \"sli.metric.custom\"; params: { index: string; good: { metrics: (({ name: string; aggregation: \"sum\"; field: string; } & { filter?: string | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: string | undefined; }))[]; equation: string; }; total: { metrics: (({ name: string; aggregation: \"sum\"; field: string; } & { filter?: string | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: string | undefined; }))[]; equation: string; }; timestampField: string; } & { filter?: string | undefined; }; } | { type: \"sli.metric.timeslice\"; params: { index: string; metric: { metrics: (({ name: string; aggregation: \"min\" | \"max\" | \"sum\" | \"avg\" | \"cardinality\" | \"last_value\" | \"std_deviation\"; field: string; } & { filter?: string | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: string | undefined; }) | ({ name: string; aggregation: \"percentile\"; field: string; percentile: number; } & { filter?: string | undefined; }))[]; equation: string; threshold: number; comparator: \"GT\" | \"GTE\" | \"LT\" | \"LTE\"; }; timestampField: string; } & { filter?: string | undefined; }; } | { type: \"sli.histogram.custom\"; params: { index: string; timestampField: string; good: ({ field: string; aggregation: \"value_count\"; } & { filter?: string | undefined; }) | ({ field: string; aggregation: \"range\"; from: number; to: number; } & { filter?: string | undefined; }); total: ({ field: string; aggregation: \"value_count\"; } & { filter?: string | undefined; }) | ({ field: string; aggregation: \"range\"; from: number; to: number; } & { filter?: string | undefined; }); } & { filter?: string | undefined; }; }; timeWindow: { duration: string; type: \"rolling\"; } | { duration: string; type: \"calendarAligned\"; }; budgetingMethod: \"occurrences\" | \"timeslices\"; objective: { target: number; } & { timesliceTarget?: number | undefined; timesliceWindow?: string | undefined; }; revision: number; settings: { syncDelay: string; frequency: string; }; enabled: boolean; tags: string[]; groupBy: string; createdAt: string; updatedAt: string; } & { instanceId?: string | undefined; }>; } & ", + " | undefined; } | undefined; tags?: string[] | undefined; groupBy?: string | undefined; }; }; }) => Promise<{ 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 | undefined; }; } | { type: \"sli.apm.transactionErrorRate\"; params: { environment: string; service: string; transactionType: string; transactionName: string; index: string; } & { filter?: string | undefined; }; } | { type: \"sli.kql.custom\"; params: { index: string; good: string; total: string; timestampField: string; } & { filter?: string | undefined; }; } | { type: \"sli.metric.custom\"; params: { index: string; good: { metrics: (({ name: string; aggregation: \"sum\"; field: string; } & { filter?: string | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: string | undefined; }))[]; equation: string; }; total: { metrics: (({ name: string; aggregation: \"sum\"; field: string; } & { filter?: string | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: string | undefined; }))[]; equation: string; }; timestampField: string; } & { filter?: string | undefined; }; } | { type: \"sli.metric.timeslice\"; params: { index: string; metric: { metrics: (({ name: string; aggregation: \"min\" | \"max\" | \"sum\" | \"avg\" | \"cardinality\" | \"last_value\" | \"std_deviation\"; field: string; } & { filter?: string | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: string | undefined; }) | ({ name: string; aggregation: \"percentile\"; field: string; percentile: number; } & { filter?: string | undefined; }))[]; equation: string; threshold: number; comparator: \"GT\" | \"GTE\" | \"LT\" | \"LTE\"; }; timestampField: string; } & { filter?: string | undefined; }; } | { type: \"sli.histogram.custom\"; params: { index: string; timestampField: string; good: ({ field: string; aggregation: \"value_count\"; } & { filter?: string | undefined; }) | ({ field: string; aggregation: \"range\"; from: number; to: number; } & { filter?: string | undefined; }); total: ({ field: string; aggregation: \"value_count\"; } & { filter?: string | undefined; }) | ({ field: string; aggregation: \"range\"; from: number; to: number; } & { filter?: string | undefined; }); } & { filter?: string | undefined; }; }; timeWindow: { duration: string; type: \"rolling\"; } | { duration: string; type: \"calendarAligned\"; }; budgetingMethod: \"occurrences\" | \"timeslices\"; objective: { target: number; } & { timesliceTarget?: number | undefined; timesliceWindow?: string | undefined; }; revision: number; settings: { syncDelay: string; frequency: string; }; enabled: boolean; tags: string[]; groupBy: string; createdAt: string; updatedAt: string; version: number; } & { instanceId?: string | undefined; }>; } & ", { "pluginId": "observability", "scope": "server", @@ -10820,7 +10870,7 @@ "section": "def-server.ObservabilityRouteHandlerResources", "text": "ObservabilityRouteHandlerResources" }, - " & { params: { path: { id: string; }; } & { query?: { instanceId?: string | undefined; } | undefined; }; }) => Promise<{ 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 | undefined; }; } | { type: \"sli.apm.transactionErrorRate\"; params: { environment: string; service: string; transactionType: string; transactionName: string; index: string; } & { filter?: string | undefined; }; } | { type: \"sli.kql.custom\"; params: { index: string; good: string; total: string; timestampField: string; } & { filter?: string | undefined; }; } | { type: \"sli.metric.custom\"; params: { index: string; good: { metrics: (({ name: string; aggregation: \"sum\"; field: string; } & { filter?: string | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: string | undefined; }))[]; equation: string; }; total: { metrics: (({ name: string; aggregation: \"sum\"; field: string; } & { filter?: string | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: string | undefined; }))[]; equation: string; }; timestampField: string; } & { filter?: string | undefined; }; } | { type: \"sli.metric.timeslice\"; params: { index: string; metric: { metrics: (({ name: string; aggregation: \"min\" | \"max\" | \"sum\" | \"avg\" | \"cardinality\" | \"last_value\" | \"std_deviation\"; field: string; } & { filter?: string | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: string | undefined; }) | ({ name: string; aggregation: \"percentile\"; field: string; percentile: number; } & { filter?: string | undefined; }))[]; equation: string; threshold: number; comparator: \"GT\" | \"GTE\" | \"LT\" | \"LTE\"; }; timestampField: string; } & { filter?: string | undefined; }; } | { type: \"sli.histogram.custom\"; params: { index: string; timestampField: string; good: ({ field: string; aggregation: \"value_count\"; } & { filter?: string | undefined; }) | ({ field: string; aggregation: \"range\"; from: number; to: number; } & { filter?: string | undefined; }); total: ({ field: string; aggregation: \"value_count\"; } & { filter?: string | undefined; }) | ({ field: string; aggregation: \"range\"; from: number; to: number; } & { filter?: string | undefined; }); } & { filter?: string | undefined; }; }; timeWindow: { duration: string; type: \"rolling\"; } | { duration: string; type: \"calendarAligned\"; }; budgetingMethod: \"occurrences\" | \"timeslices\"; objective: { target: number; } & { timesliceTarget?: number | undefined; timesliceWindow?: string | undefined; }; revision: number; settings: { syncDelay: string; frequency: string; }; enabled: boolean; tags: string[]; groupBy: string; createdAt: string; updatedAt: string; } & { instanceId?: string | undefined; } & { summary: { status: \"HEALTHY\" | \"NO_DATA\" | \"DEGRADING\" | \"VIOLATED\"; sliValue: number; errorBudget: { initial: number; consumed: number; remaining: number; isEstimated: boolean; }; }; }>; } & ", + " & { params: { path: { id: string; }; } & { query?: { instanceId?: string | undefined; } | undefined; }; }) => Promise<{ 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 | undefined; }; } | { type: \"sli.apm.transactionErrorRate\"; params: { environment: string; service: string; transactionType: string; transactionName: string; index: string; } & { filter?: string | undefined; }; } | { type: \"sli.kql.custom\"; params: { index: string; good: string; total: string; timestampField: string; } & { filter?: string | undefined; }; } | { type: \"sli.metric.custom\"; params: { index: string; good: { metrics: (({ name: string; aggregation: \"sum\"; field: string; } & { filter?: string | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: string | undefined; }))[]; equation: string; }; total: { metrics: (({ name: string; aggregation: \"sum\"; field: string; } & { filter?: string | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: string | undefined; }))[]; equation: string; }; timestampField: string; } & { filter?: string | undefined; }; } | { type: \"sli.metric.timeslice\"; params: { index: string; metric: { metrics: (({ name: string; aggregation: \"min\" | \"max\" | \"sum\" | \"avg\" | \"cardinality\" | \"last_value\" | \"std_deviation\"; field: string; } & { filter?: string | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: string | undefined; }) | ({ name: string; aggregation: \"percentile\"; field: string; percentile: number; } & { filter?: string | undefined; }))[]; equation: string; threshold: number; comparator: \"GT\" | \"GTE\" | \"LT\" | \"LTE\"; }; timestampField: string; } & { filter?: string | undefined; }; } | { type: \"sli.histogram.custom\"; params: { index: string; timestampField: string; good: ({ field: string; aggregation: \"value_count\"; } & { filter?: string | undefined; }) | ({ field: string; aggregation: \"range\"; from: number; to: number; } & { filter?: string | undefined; }); total: ({ field: string; aggregation: \"value_count\"; } & { filter?: string | undefined; }) | ({ field: string; aggregation: \"range\"; from: number; to: number; } & { filter?: string | undefined; }); } & { filter?: string | undefined; }; }; timeWindow: { duration: string; type: \"rolling\"; } | { duration: string; type: \"calendarAligned\"; }; budgetingMethod: \"occurrences\" | \"timeslices\"; objective: { target: number; } & { timesliceTarget?: number | undefined; timesliceWindow?: string | undefined; }; revision: number; settings: { syncDelay: string; frequency: string; }; enabled: boolean; tags: string[]; groupBy: string; createdAt: string; updatedAt: string; version: number; } & { instanceId?: string | undefined; } & { summary: { status: \"HEALTHY\" | \"NO_DATA\" | \"DEGRADING\" | \"VIOLATED\"; sliValue: number; errorBudget: { initial: number; consumed: number; remaining: number; isEstimated: boolean; }; }; }>; } & ", { "pluginId": "observability", "scope": "server", @@ -10862,7 +10912,7 @@ "section": "def-server.ObservabilityRouteHandlerResources", "text": "ObservabilityRouteHandlerResources" }, - " & { params?: { query?: { kqlQuery?: string | undefined; page?: string | undefined; perPage?: string | undefined; sortBy?: \"status\" | \"error_budget_consumed\" | \"error_budget_remaining\" | \"sli_value\" | undefined; sortDirection?: \"asc\" | \"desc\" | undefined; } | undefined; } | undefined; }) => Promise<{ 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 | undefined; }; } | { type: \"sli.apm.transactionErrorRate\"; params: { environment: string; service: string; transactionType: string; transactionName: string; index: string; } & { filter?: string | undefined; }; } | { type: \"sli.kql.custom\"; params: { index: string; good: string; total: string; timestampField: string; } & { filter?: string | undefined; }; } | { type: \"sli.metric.custom\"; params: { index: string; good: { metrics: (({ name: string; aggregation: \"sum\"; field: string; } & { filter?: string | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: string | undefined; }))[]; equation: string; }; total: { metrics: (({ name: string; aggregation: \"sum\"; field: string; } & { filter?: string | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: string | undefined; }))[]; equation: string; }; timestampField: string; } & { filter?: string | undefined; }; } | { type: \"sli.metric.timeslice\"; params: { index: string; metric: { metrics: (({ name: string; aggregation: \"min\" | \"max\" | \"sum\" | \"avg\" | \"cardinality\" | \"last_value\" | \"std_deviation\"; field: string; } & { filter?: string | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: string | undefined; }) | ({ name: string; aggregation: \"percentile\"; field: string; percentile: number; } & { filter?: string | undefined; }))[]; equation: string; threshold: number; comparator: \"GT\" | \"GTE\" | \"LT\" | \"LTE\"; }; timestampField: string; } & { filter?: string | undefined; }; } | { type: \"sli.histogram.custom\"; params: { index: string; timestampField: string; good: ({ field: string; aggregation: \"value_count\"; } & { filter?: string | undefined; }) | ({ field: string; aggregation: \"range\"; from: number; to: number; } & { filter?: string | undefined; }); total: ({ field: string; aggregation: \"value_count\"; } & { filter?: string | undefined; }) | ({ field: string; aggregation: \"range\"; from: number; to: number; } & { filter?: string | undefined; }); } & { filter?: string | undefined; }; }; timeWindow: { duration: string; type: \"rolling\"; } | { duration: string; type: \"calendarAligned\"; }; budgetingMethod: \"occurrences\" | \"timeslices\"; objective: { target: number; } & { timesliceTarget?: number | undefined; timesliceWindow?: string | undefined; }; revision: number; settings: { syncDelay: string; frequency: string; }; enabled: boolean; tags: string[]; groupBy: string; createdAt: string; updatedAt: string; } & { instanceId?: string | undefined; } & { summary: { status: \"HEALTHY\" | \"NO_DATA\" | \"DEGRADING\" | \"VIOLATED\"; sliValue: number; errorBudget: { initial: number; consumed: number; remaining: number; isEstimated: boolean; }; }; })[]; }>; } & ", + " & { params?: { query?: { kqlQuery?: string | undefined; page?: string | undefined; perPage?: string | undefined; sortBy?: \"status\" | \"error_budget_consumed\" | \"error_budget_remaining\" | \"sli_value\" | undefined; sortDirection?: \"asc\" | \"desc\" | undefined; } | undefined; } | undefined; }) => Promise<{ 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 | undefined; }; } | { type: \"sli.apm.transactionErrorRate\"; params: { environment: string; service: string; transactionType: string; transactionName: string; index: string; } & { filter?: string | undefined; }; } | { type: \"sli.kql.custom\"; params: { index: string; good: string; total: string; timestampField: string; } & { filter?: string | undefined; }; } | { type: \"sli.metric.custom\"; params: { index: string; good: { metrics: (({ name: string; aggregation: \"sum\"; field: string; } & { filter?: string | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: string | undefined; }))[]; equation: string; }; total: { metrics: (({ name: string; aggregation: \"sum\"; field: string; } & { filter?: string | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: string | undefined; }))[]; equation: string; }; timestampField: string; } & { filter?: string | undefined; }; } | { type: \"sli.metric.timeslice\"; params: { index: string; metric: { metrics: (({ name: string; aggregation: \"min\" | \"max\" | \"sum\" | \"avg\" | \"cardinality\" | \"last_value\" | \"std_deviation\"; field: string; } & { filter?: string | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: string | undefined; }) | ({ name: string; aggregation: \"percentile\"; field: string; percentile: number; } & { filter?: string | undefined; }))[]; equation: string; threshold: number; comparator: \"GT\" | \"GTE\" | \"LT\" | \"LTE\"; }; timestampField: string; } & { filter?: string | undefined; }; } | { type: \"sli.histogram.custom\"; params: { index: string; timestampField: string; good: ({ field: string; aggregation: \"value_count\"; } & { filter?: string | undefined; }) | ({ field: string; aggregation: \"range\"; from: number; to: number; } & { filter?: string | undefined; }); total: ({ field: string; aggregation: \"value_count\"; } & { filter?: string | undefined; }) | ({ field: string; aggregation: \"range\"; from: number; to: number; } & { filter?: string | undefined; }); } & { filter?: string | undefined; }; }; timeWindow: { duration: string; type: \"rolling\"; } | { duration: string; type: \"calendarAligned\"; }; budgetingMethod: \"occurrences\" | \"timeslices\"; objective: { target: number; } & { timesliceTarget?: number | undefined; timesliceWindow?: string | undefined; }; revision: number; settings: { syncDelay: string; frequency: string; }; enabled: boolean; tags: string[]; groupBy: string; createdAt: string; updatedAt: string; version: number; } & { instanceId?: string | undefined; } & { summary: { status: \"HEALTHY\" | \"NO_DATA\" | \"DEGRADING\" | \"VIOLATED\"; sliValue: number; errorBudget: { initial: number; consumed: number; remaining: number; isEstimated: boolean; }; }; })[]; }>; } & ", { "pluginId": "observability", "scope": "server", @@ -10870,12 +10920,18 @@ "section": "def-server.ObservabilityRouteCreateOptions", "text": "ObservabilityRouteCreateOptions" }, - "; \"GET /internal/observability/slos/_definitions\": { endpoint: \"GET /internal/observability/slos/_definitions\"; params?: ", - "TypeC", + "; \"GET /api/observability/slos/_definitions 2023-10-31\": { endpoint: \"GET /api/observability/slos/_definitions 2023-10-31\"; params?: ", + "PartialC", "<{ query: ", - "TypeC", + "PartialC", "<{ search: ", "StringC", + "; includeOutdatedOnly: ", + "Type", + "; page: ", + "StringC", + "; perPage: ", + "StringC", "; }>; }> | undefined; handler: ({}: ", { "pluginId": "observability", @@ -10884,7 +10940,7 @@ "section": "def-server.ObservabilityRouteHandlerResources", "text": "ObservabilityRouteHandlerResources" }, - " & { params: { query: { search: string; }; }; }) => Promise<({ 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 | undefined; }; } | { type: \"sli.apm.transactionErrorRate\"; params: { environment: string; service: string; transactionType: string; transactionName: string; index: string; } & { filter?: string | undefined; }; } | { type: \"sli.kql.custom\"; params: { index: string; good: string; total: string; timestampField: string; } & { filter?: string | undefined; }; } | { type: \"sli.metric.custom\"; params: { index: string; good: { metrics: (({ name: string; aggregation: \"sum\"; field: string; } & { filter?: string | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: string | undefined; }))[]; equation: string; }; total: { metrics: (({ name: string; aggregation: \"sum\"; field: string; } & { filter?: string | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: string | undefined; }))[]; equation: string; }; timestampField: string; } & { filter?: string | undefined; }; } | { type: \"sli.metric.timeslice\"; params: { index: string; metric: { metrics: (({ name: string; aggregation: \"min\" | \"max\" | \"sum\" | \"avg\" | \"cardinality\" | \"last_value\" | \"std_deviation\"; field: string; } & { filter?: string | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: string | undefined; }) | ({ name: string; aggregation: \"percentile\"; field: string; percentile: number; } & { filter?: string | undefined; }))[]; equation: string; threshold: number; comparator: \"GT\" | \"GTE\" | \"LT\" | \"LTE\"; }; timestampField: string; } & { filter?: string | undefined; }; } | { type: \"sli.histogram.custom\"; params: { index: string; timestampField: string; good: ({ field: string; aggregation: \"value_count\"; } & { filter?: string | undefined; }) | ({ field: string; aggregation: \"range\"; from: number; to: number; } & { filter?: string | undefined; }); total: ({ field: string; aggregation: \"value_count\"; } & { filter?: string | undefined; }) | ({ field: string; aggregation: \"range\"; from: number; to: number; } & { filter?: string | undefined; }); } & { filter?: string | undefined; }; }; timeWindow: { duration: string; type: \"rolling\"; } | { duration: string; type: \"calendarAligned\"; }; budgetingMethod: \"occurrences\" | \"timeslices\"; objective: { target: number; } & { timesliceTarget?: number | undefined; timesliceWindow?: string | undefined; }; revision: number; settings: { syncDelay: string; frequency: string; }; enabled: boolean; tags: string[]; groupBy: string; createdAt: string; updatedAt: string; } & { instanceId?: string | undefined; })[]>; } & ", + " & { params?: { query?: { search?: string | undefined; includeOutdatedOnly?: boolean | undefined; page?: string | undefined; perPage?: string | undefined; } | undefined; } | undefined; }) => Promise<{ 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 | undefined; }; } | { type: \"sli.apm.transactionErrorRate\"; params: { environment: string; service: string; transactionType: string; transactionName: string; index: string; } & { filter?: string | undefined; }; } | { type: \"sli.kql.custom\"; params: { index: string; good: string; total: string; timestampField: string; } & { filter?: string | undefined; }; } | { type: \"sli.metric.custom\"; params: { index: string; good: { metrics: (({ name: string; aggregation: \"sum\"; field: string; } & { filter?: string | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: string | undefined; }))[]; equation: string; }; total: { metrics: (({ name: string; aggregation: \"sum\"; field: string; } & { filter?: string | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: string | undefined; }))[]; equation: string; }; timestampField: string; } & { filter?: string | undefined; }; } | { type: \"sli.metric.timeslice\"; params: { index: string; metric: { metrics: (({ name: string; aggregation: \"min\" | \"max\" | \"sum\" | \"avg\" | \"cardinality\" | \"last_value\" | \"std_deviation\"; field: string; } & { filter?: string | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: string | undefined; }) | ({ name: string; aggregation: \"percentile\"; field: string; percentile: number; } & { filter?: string | undefined; }))[]; equation: string; threshold: number; comparator: \"GT\" | \"GTE\" | \"LT\" | \"LTE\"; }; timestampField: string; } & { filter?: string | undefined; }; } | { type: \"sli.histogram.custom\"; params: { index: string; timestampField: string; good: ({ field: string; aggregation: \"value_count\"; } & { filter?: string | undefined; }) | ({ field: string; aggregation: \"range\"; from: number; to: number; } & { filter?: string | undefined; }); total: ({ field: string; aggregation: \"value_count\"; } & { filter?: string | undefined; }) | ({ field: string; aggregation: \"range\"; from: number; to: number; } & { filter?: string | undefined; }); } & { filter?: string | undefined; }; }; timeWindow: { duration: string; type: \"rolling\"; } | { duration: string; type: \"calendarAligned\"; }; budgetingMethod: \"occurrences\" | \"timeslices\"; objective: { target: number; } & { timesliceTarget?: number | undefined; timesliceWindow?: string | undefined; }; revision: number; settings: { syncDelay: string; frequency: string; }; enabled: boolean; tags: string[]; groupBy: string; createdAt: string; updatedAt: string; version: number; } & { instanceId?: string | undefined; })[]; }>; } & ", { "pluginId": "observability", "scope": "server", diff --git a/api_docs/observability.mdx b/api_docs/observability.mdx index fc9a3c436b5b9..0c57a24e4c449 100644 --- a/api_docs/observability.mdx +++ b/api_docs/observability.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/observability title: "observability" image: https://source.unsplash.com/400x175/?github description: API docs for the observability plugin -date: 2023-11-14 +date: 2023-11-16 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'observability'] --- import observabilityObj from './observability.devdocs.json'; diff --git a/api_docs/observability_a_i_assistant.devdocs.json b/api_docs/observability_a_i_assistant.devdocs.json index 9ef9ee9d5273f..29b5cec0de507 100644 --- a/api_docs/observability_a_i_assistant.devdocs.json +++ b/api_docs/observability_a_i_assistant.devdocs.json @@ -415,7 +415,7 @@ "Type", "; }>]>; }> | undefined; handler: ({}: ", "ObservabilityAIAssistantRouteHandlerResources", - " & { params: { body: { featureIds: string[]; start: string; end: string; } & { filter?: string | undefined; includeRecovered?: boolean | undefined; }; }; }) => Promise<{ content: { total: number; alerts: OutputOf>[]; }; }>; } & ", + " & { params: { body: { featureIds: string[]; start: string; end: string; } & { filter?: string | undefined; includeRecovered?: boolean | undefined; }; }; }) => Promise<{ content: { total: number; alerts: OutputOf>[]; }; }>; } & ", "ObservabilityAIAssistantRouteCreateOptions", "; \"GET /internal/observability_ai_assistant/functions/kb_status\": { endpoint: \"GET /internal/observability_ai_assistant/functions/kb_status\"; params?: undefined; handler: ({}: ", "ObservabilityAIAssistantRouteHandlerResources", @@ -814,7 +814,7 @@ "Type", "; }>]>; }> | undefined; handler: ({}: ", "ObservabilityAIAssistantRouteHandlerResources", - " & { params: { body: { featureIds: string[]; start: string; end: string; } & { filter?: string | undefined; includeRecovered?: boolean | undefined; }; }; }) => Promise<{ content: { total: number; alerts: OutputOf>[]; }; }>; } & ", + " & { params: { body: { featureIds: string[]; start: string; end: string; } & { filter?: string | undefined; includeRecovered?: boolean | undefined; }; }; }) => Promise<{ content: { total: number; alerts: OutputOf>[]; }; }>; } & ", "ObservabilityAIAssistantRouteCreateOptions", "; \"GET /internal/observability_ai_assistant/functions/kb_status\": { endpoint: \"GET /internal/observability_ai_assistant/functions/kb_status\"; params?: undefined; handler: ({}: ", "ObservabilityAIAssistantRouteHandlerResources", @@ -1319,7 +1319,7 @@ "Type", "; }>]>; }> | undefined; handler: ({}: ", "ObservabilityAIAssistantRouteHandlerResources", - " & { params: { body: { featureIds: string[]; start: string; end: string; } & { filter?: string | undefined; includeRecovered?: boolean | undefined; }; }; }) => Promise<{ content: { total: number; alerts: OutputOf>[]; }; }>; } & ", + " & { params: { body: { featureIds: string[]; start: string; end: string; } & { filter?: string | undefined; includeRecovered?: boolean | undefined; }; }; }) => Promise<{ content: { total: number; alerts: OutputOf>[]; }; }>; } & ", "ObservabilityAIAssistantRouteCreateOptions", "; \"GET /internal/observability_ai_assistant/functions/kb_status\": { endpoint: \"GET /internal/observability_ai_assistant/functions/kb_status\"; params?: undefined; handler: ({}: ", "ObservabilityAIAssistantRouteHandlerResources", diff --git a/api_docs/observability_a_i_assistant.mdx b/api_docs/observability_a_i_assistant.mdx index bc9954cf3904d..dca8e221f5e7a 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: 2023-11-14 +date: 2023-11-16 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'observabilityAIAssistant'] --- import observabilityAIAssistantObj from './observability_a_i_assistant.devdocs.json'; diff --git a/api_docs/observability_log_explorer.mdx b/api_docs/observability_log_explorer.mdx index d140ddcbafc73..a49295da03a0f 100644 --- a/api_docs/observability_log_explorer.mdx +++ b/api_docs/observability_log_explorer.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/observabilityLogExplorer title: "observabilityLogExplorer" image: https://source.unsplash.com/400x175/?github description: API docs for the observabilityLogExplorer plugin -date: 2023-11-14 +date: 2023-11-16 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'observabilityLogExplorer'] --- import observabilityLogExplorerObj from './observability_log_explorer.devdocs.json'; diff --git a/api_docs/observability_onboarding.mdx b/api_docs/observability_onboarding.mdx index 353dbc3122ebc..7d96d1aca7a94 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: 2023-11-14 +date: 2023-11-16 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 917a310469e51..5b32bb8b68359 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: 2023-11-14 +date: 2023-11-16 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'observabilityShared'] --- import observabilitySharedObj from './observability_shared.devdocs.json'; diff --git a/api_docs/osquery.devdocs.json b/api_docs/osquery.devdocs.json index 915835e36711b..f03a3b873a0ca 100644 --- a/api_docs/osquery.devdocs.json +++ b/api_docs/osquery.devdocs.json @@ -301,7 +301,7 @@ "label": "createActionService", "description": [], "signature": [ - "{ create: (params: { agent_ids?: string[] | undefined; agent_all?: boolean | undefined; agent_platforms?: string[] | undefined; agent_policy_ids?: string[] | undefined; query?: string | undefined; queries?: { id: string; query: string; ecs_mapping: { [x: string]: { field?: string | undefined; value?: string | string[] | undefined; }; } | undefined; version: string | undefined; platform: string | undefined; removed: boolean | undefined; snapshot: boolean | undefined; }[] | undefined; saved_query_id?: string | undefined; ecs_mapping?: { [x: string]: { field?: string | undefined; value?: string | string[] | undefined; }; } | undefined; pack_id?: string | undefined; alert_ids?: string[] | undefined; case_ids?: string[] | undefined; event_ids?: string[] | undefined; metadata?: object | undefined; }, alertData?: OutputOf> | undefined) => Promise<{ response: { action_id: string; '@timestamp': string; expiration: string; type: string; input_type: string; alert_ids: string[] | undefined; event_ids: string[] | undefined; case_ids: string[] | undefined; agent_ids: string[] | undefined; agent_all: boolean | undefined; agent_platforms: string[] | undefined; agent_policy_ids: string[] | undefined; agents: string[]; user_id: string | undefined; metadata: object | undefined; pack_id: string | undefined; pack_name: string | undefined; pack_prebuilt: boolean | undefined; queries: ", + "{ create: (params: { agent_ids?: string[] | undefined; agent_all?: boolean | undefined; agent_platforms?: string[] | undefined; agent_policy_ids?: string[] | undefined; query?: string | undefined; queries?: { id: string; query: string; ecs_mapping: { [x: string]: { field?: string | undefined; value?: string | string[] | undefined; }; } | undefined; version: string | undefined; platform: string | undefined; removed: boolean | undefined; snapshot: boolean | undefined; }[] | undefined; saved_query_id?: string | undefined; timeout?: number | undefined; ecs_mapping?: { [x: string]: { field?: string | undefined; value?: string | string[] | undefined; }; } | undefined; pack_id?: string | undefined; alert_ids?: string[] | undefined; case_ids?: string[] | undefined; event_ids?: string[] | undefined; metadata?: object | undefined; }, alertData?: OutputOf> | undefined) => Promise<{ response: { action_id: string; '@timestamp': string; expiration: string; type: string; input_type: string; alert_ids: string[] | undefined; event_ids: string[] | undefined; case_ids: string[] | undefined; agent_ids: string[] | undefined; agent_all: boolean | undefined; agent_platforms: string[] | undefined; agent_policy_ids: string[] | undefined; agents: string[]; user_id: string | undefined; metadata: object | undefined; pack_id: string | undefined; pack_name: string | undefined; pack_prebuilt: boolean | undefined; queries: ", "Dictionary", "[]; }; fleetActionsCount: number; }>; stop: () => void; }" ], diff --git a/api_docs/osquery.mdx b/api_docs/osquery.mdx index b2bbd4cbfc5c7..34c0045ada190 100644 --- a/api_docs/osquery.mdx +++ b/api_docs/osquery.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/osquery title: "osquery" image: https://source.unsplash.com/400x175/?github description: API docs for the osquery plugin -date: 2023-11-14 +date: 2023-11-16 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 136ba32c81d60..fbebc63aaa1f8 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: 2023-11-14 +date: 2023-11-16 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 7957992ddfa5d..bb621aec7465a 100644 --- a/api_docs/plugin_directory.mdx +++ b/api_docs/plugin_directory.mdx @@ -7,7 +7,7 @@ id: kibDevDocsPluginDirectory slug: /kibana-dev-docs/api-meta/plugin-api-directory title: Directory description: Directory of public APIs available through plugins or packages. -date: 2023-11-14 +date: 2023-11-16 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 | |--------------|----------|------------------------| -| 702 | 594 | 41 | +| 711 | 603 | 40 | ### Public API health stats | API Count | Any Count | Missing comments | Missing exports | |--------------|----------|-----------------|--------| -| 76123 | 233 | 65082 | 1598 | +| 76352 | 233 | 65301 | 1602 | ## Plugin Directory @@ -30,7 +30,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [@elastic/response-ops](https://github.com/orgs/elastic/teams/response-ops) | - | 269 | 0 | 263 | 31 | | | [@elastic/appex-sharedux @elastic/platform-deployment-management](https://github.com/orgs/elastic/teams/appex-sharedux ) | - | 17 | 1 | 15 | 2 | | | [@elastic/ml-ui](https://github.com/orgs/elastic/teams/ml-ui) | AIOps plugin maintained by ML team. | 69 | 1 | 4 | 1 | -| | [@elastic/response-ops](https://github.com/orgs/elastic/teams/response-ops) | - | 809 | 1 | 778 | 50 | +| | [@elastic/response-ops](https://github.com/orgs/elastic/teams/response-ops) | - | 810 | 1 | 779 | 50 | | | [@elastic/obs-ux-infra_services-team](https://github.com/orgs/elastic/teams/obs-ux-infra_services-team) | The user interface for Elastic APM | 29 | 0 | 29 | 120 | | | [@elastic/obs-knowledge-team](https://github.com/orgs/elastic/teams/obs-knowledge-team) | - | 9 | 0 | 9 | 0 | | | [@elastic/obs-knowledge-team](https://github.com/orgs/elastic/teams/obs-knowledge-team) | Asset manager plugin for entity assets (inventory, topology, etc) | 9 | 0 | 9 | 2 | @@ -56,11 +56,11 @@ 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 | 268 | 0 | 249 | 1 | | | [@elastic/kibana-presentation](https://github.com/orgs/elastic/teams/kibana-presentation) | Adds the Dashboard app to Kibana | 109 | 0 | 106 | 11 | | | [@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. | 3193 | 32 | 2542 | 22 | +| | [@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. | 3197 | 32 | 2545 | 22 | | | [@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 | | | [@elastic/kibana-data-discovery](https://github.com/orgs/elastic/teams/kibana-data-discovery) | Data view management app | 2 | 0 | 2 | 0 | -| | [@elastic/kibana-data-discovery](https://github.com/orgs/elastic/teams/kibana-data-discovery) | 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. | 918 | 0 | 255 | 4 | +| | [@elastic/kibana-data-discovery](https://github.com/orgs/elastic/teams/kibana-data-discovery) | 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. | 922 | 0 | 257 | 4 | | | [@elastic/ml-ui](https://github.com/orgs/elastic/teams/ml-ui) | The Data Visualizer tools help you understand your data, by analyzing the metrics and fields in a log file or an existing Elasticsearch index. | 31 | 3 | 25 | 1 | | | [@elastic/obs-ux-logs-team](https://github.com/orgs/elastic/teams/obs-ux-logs-team) | This plugin introduces the concept of dataset quality, where users can easily get an overview on the datasets they have. | 3 | 0 | 3 | 0 | | | [@elastic/platform-deployment-management](https://github.com/orgs/elastic/teams/platform-deployment-management) | - | 12 | 0 | 10 | 3 | @@ -114,7 +114,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [@elastic/kibana-presentation](https://github.com/orgs/elastic/teams/kibana-presentation) | - | 123 | 2 | 96 | 4 | | | [@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/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 6 | 0 | 6 | 0 | -| | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 167 | 0 | 133 | 3 | +| | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 161 | 0 | 127 | 3 | | kibanaUsageCollection | [@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) | - | 610 | 3 | 417 | 9 | | | [@elastic/kibana-cloud-security-posture](https://github.com/orgs/elastic/teams/kibana-cloud-security-posture) | - | 5 | 0 | 5 | 1 | @@ -129,7 +129,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | logstash | [@elastic/logstash](https://github.com/orgs/elastic/teams/logstash) | - | 0 | 0 | 0 | 0 | | | [@elastic/platform-deployment-management](https://github.com/orgs/elastic/teams/platform-deployment-management) | - | 45 | 0 | 45 | 7 | | | [@elastic/kibana-gis](https://github.com/orgs/elastic/teams/kibana-gis) | - | 260 | 0 | 259 | 29 | -| | [@elastic/kibana-gis](https://github.com/orgs/elastic/teams/kibana-gis) | - | 68 | 0 | 68 | 0 | +| | [@elastic/kibana-gis](https://github.com/orgs/elastic/teams/kibana-gis) | - | 60 | 0 | 60 | 0 | | | [@elastic/obs-knowledge-team](https://github.com/orgs/elastic/teams/obs-knowledge-team) | Exposes utilities for accessing metrics data | 104 | 8 | 104 | 4 | | | [@elastic/ml-ui](https://github.com/orgs/elastic/teams/ml-ui) | This plugin provides access to the machine learning features provided by Elastic. | 150 | 3 | 64 | 33 | | | [@elastic/obs-ux-infra_services-team](https://github.com/orgs/elastic/teams/obs-ux-infra_services-team) | - | 15 | 3 | 13 | 1 | @@ -149,7 +149,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [@elastic/obs-ux-infra_services-team](https://github.com/orgs/elastic/teams/obs-ux-infra_services-team) | - | 16 | 1 | 16 | 0 | | | [@elastic/obs-ux-infra_services-team](https://github.com/orgs/elastic/teams/obs-ux-infra_services-team) | - | 22 | 0 | 22 | 7 | | | [@elastic/platform-deployment-management](https://github.com/orgs/elastic/teams/platform-deployment-management) | - | 23 | 0 | 23 | 0 | -| | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | Reporting Services enables applications to feature reports that the user can automate with Watcher and download later. | 42 | 0 | 22 | 5 | +| | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | Reporting Services enables applications to feature reports that the user can automate with Watcher and download later. | 22 | 0 | 6 | 0 | | | [@elastic/platform-deployment-management](https://github.com/orgs/elastic/teams/platform-deployment-management) | - | 21 | 0 | 21 | 0 | | | [@elastic/response-ops](https://github.com/orgs/elastic/teams/response-ops) | - | 267 | 0 | 238 | 14 | | | [@elastic/platform-deployment-management](https://github.com/orgs/elastic/teams/platform-deployment-management) | - | 24 | 0 | 19 | 2 | @@ -160,7 +160,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 104 | 0 | 56 | 1 | | | [@elastic/kibana-data-discovery](https://github.com/orgs/elastic/teams/kibana-data-discovery) | This plugin contains the definition and helper methods around saved searches, used by discover and visualizations. | 75 | 0 | 74 | 3 | | | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 32 | 0 | 13 | 0 | -| | [@elastic/kibana-reporting-services](https://github.com/orgs/elastic/teams/kibana-reporting-services) | Kibana Screenshotting Plugin | 27 | 0 | 8 | 5 | +| | [@elastic/kibana-reporting-services](https://github.com/orgs/elastic/teams/kibana-reporting-services) | Kibana Screenshotting Plugin | 32 | 0 | 8 | 4 | | searchprofiler | [@elastic/platform-deployment-management](https://github.com/orgs/elastic/teams/platform-deployment-management) | - | 0 | 0 | 0 | 0 | | | [@elastic/kibana-security](https://github.com/orgs/elastic/teams/kibana-security) | This plugin provides authentication and authorization features, and exposes functionality to understand the capabilities of the currently authenticated user. | 270 | 0 | 87 | 3 | | | [@elastic/security-solution](https://github.com/orgs/elastic/teams/security-solution) | - | 175 | 0 | 106 | 35 | @@ -176,7 +176,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [@elastic/response-ops](https://github.com/orgs/elastic/teams/response-ops) | - | 23 | 0 | 23 | 3 | | | [@elastic/response-ops](https://github.com/orgs/elastic/teams/response-ops) | - | 4 | 0 | 4 | 1 | | synthetics | [@elastic/obs-ux-infra_services-team](https://github.com/orgs/elastic/teams/obs-ux-infra_services-team) | This plugin visualizes data from Synthetics and Heartbeat, and integrates with other Observability solutions. | 0 | 0 | 0 | 0 | -| | [@elastic/response-ops](https://github.com/orgs/elastic/teams/response-ops) | - | 96 | 0 | 53 | 6 | +| | [@elastic/response-ops](https://github.com/orgs/elastic/teams/response-ops) | - | 105 | 0 | 62 | 5 | | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 45 | 0 | 1 | 0 | | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 31 | 0 | 26 | 6 | | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 1 | 0 | 1 | 0 | @@ -186,7 +186,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [@elastic/security-threat-hunting-investigations](https://github.com/orgs/elastic/teams/security-threat-hunting-investigations) | - | 240 | 1 | 196 | 17 | | | [@elastic/ml-ui](https://github.com/orgs/elastic/teams/ml-ui) | This plugin provides access to the transforms features provided by Elastic. Transforms enable you to convert existing Elasticsearch indices into summarized indices, which provide opportunities for new insights and analytics. | 4 | 0 | 4 | 1 | | translations | [@elastic/kibana-localization](https://github.com/orgs/elastic/teams/kibana-localization) | - | 0 | 0 | 0 | 0 | -| | [@elastic/response-ops](https://github.com/orgs/elastic/teams/response-ops) | - | 581 | 1 | 555 | 55 | +| | [@elastic/response-ops](https://github.com/orgs/elastic/teams/response-ops) | - | 583 | 1 | 557 | 55 | | | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | Adds UI Actions service to Kibana | 145 | 0 | 103 | 9 | | | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | Extends UI Actions plugin with more functionality | 212 | 0 | 145 | 10 | | | [@elastic/kibana-data-discovery](https://github.com/orgs/elastic/teams/kibana-data-discovery) | This plugin contains services reliant on the plugin lifecycle for the unified doc viewer component (see @kbn/unified-doc-viewer). | 13 | 0 | 10 | 3 | @@ -227,6 +227,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [@elastic/response-ops](https://github.com/orgs/elastic/teams/response-ops) | - | 11 | 0 | 10 | 1 | | | [@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 | @@ -457,8 +458,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [@elastic/kibana-operations](https://github.com/orgs/elastic/teams/kibana-operations) | - | 29 | 0 | 29 | 1 | | | [@elastic/kibana-operations](https://github.com/orgs/elastic/teams/kibana-operations) | - | 1 | 0 | 0 | 0 | | | [@elastic/platform-deployment-management](https://github.com/orgs/elastic/teams/platform-deployment-management) | - | 1 | 0 | 1 | 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) | - | 10 | 0 | 10 | 0 | +| | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 10 | 0 | 10 | 1 | | | [@elastic/platform-onboarding](https://github.com/orgs/elastic/teams/platform-onboarding) | - | 54 | 0 | 52 | 3 | | | [@elastic/kibana-security](https://github.com/orgs/elastic/teams/kibana-security) | - | 33 | 3 | 24 | 6 | | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 3 | 0 | 3 | 0 | @@ -519,12 +519,12 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [@elastic/ml-ui](https://github.com/orgs/elastic/teams/ml-ui) | - | 31 | 1 | 24 | 1 | | | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 78 | 0 | 76 | 3 | | | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 55 | 1 | 50 | 0 | -| | [@elastic/actionable-observability](https://github.com/orgs/elastic/teams/actionable-observability) | - | 13 | 0 | 13 | 3 | -| | [@elastic/actionable-observability](https://github.com/orgs/elastic/teams/actionable-observability) | - | 99 | 1 | 99 | 0 | +| | [@elastic/obs-ux-management-team](https://github.com/orgs/elastic/teams/obs-ux-management-team) | - | 13 | 0 | 13 | 3 | +| | [@elastic/obs-ux-management-team](https://github.com/orgs/elastic/teams/obs-ux-management-team) | - | 99 | 1 | 99 | 0 | | | [@elastic/security-detection-rule-management](https://github.com/orgs/elastic/teams/security-detection-rule-management) | - | 7 | 0 | 7 | 0 | | | [@elastic/kibana-operations](https://github.com/orgs/elastic/teams/kibana-operations) | - | 45 | 0 | 45 | 10 | | | [@elastic/kibana-operations](https://github.com/orgs/elastic/teams/kibana-operations) | - | 51 | 5 | 34 | 0 | -| | [@elastic/security-asset-management](https://github.com/orgs/elastic/teams/security-asset-management) | - | 62 | 0 | 62 | 0 | +| | [@elastic/security-asset-management](https://github.com/orgs/elastic/teams/security-asset-management) | - | 66 | 0 | 66 | 0 | | | [@elastic/kibana-performance-testing](https://github.com/orgs/elastic/teams/kibana-performance-testing) | - | 3 | 0 | 3 | 1 | | | [@elastic/kibana-operations](https://github.com/orgs/elastic/teams/kibana-operations) | - | 1 | 0 | 1 | 0 | | | [@elastic/kibana-operations](https://github.com/orgs/elastic/teams/kibana-operations) | - | 1 | 0 | 1 | 0 | @@ -541,7 +541,16 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [@elastic/kibana-operations](https://github.com/orgs/elastic/teams/kibana-operations) | - | 40 | 0 | 38 | 5 | | | [@elastic/kibana-operations](https://github.com/orgs/elastic/teams/kibana-operations) | - | 13 | 0 | 9 | 0 | | | [@elastic/kibana-operations](https://github.com/orgs/elastic/teams/kibana-operations) | - | 6 | 0 | 6 | 1 | -| | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 73 | 0 | 65 | 0 | +| | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 80 | 0 | 72 | 7 | +| | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 50 | 0 | 50 | 3 | +| | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 17 | 0 | 16 | 0 | +| | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 32 | 0 | 31 | 0 | +| | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 14 | 0 | 11 | 0 | +| | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 16 | 0 | 15 | 0 | +| | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 13 | 0 | 11 | 0 | +| | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 2 | 0 | 2 | 0 | +| | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 5 | 0 | 5 | 0 | +| | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 78 | 0 | 77 | 0 | | | [@elastic/kibana-data-discovery](https://github.com/orgs/elastic/teams/kibana-data-discovery) | A component for creating resizable layouts containing a fixed width panel and a flexible panel, with support for horizontal and vertical layouts. | 18 | 0 | 5 | 0 | | | [@elastic/kibana-operations](https://github.com/orgs/elastic/teams/kibana-operations) | - | 13 | 2 | 8 | 0 | | | [@elastic/response-ops](https://github.com/orgs/elastic/teams/response-ops) | - | 16 | 0 | 16 | 1 | @@ -583,7 +592,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [@elastic/obs-ux-infra_services-team](https://github.com/orgs/elastic/teams/obs-ux-infra_services-team) | - | 4 | 0 | 4 | 0 | | | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 3 | 0 | 2 | 2 | | | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 8 | 0 | 2 | 1 | -| | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 28 | 0 | 10 | 0 | +| | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 26 | 0 | 8 | 0 | | | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 10 | 0 | 4 | 0 | | | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 32 | 0 | 28 | 0 | | | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 60 | 0 | 49 | 5 | @@ -619,7 +628,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 2 | 0 | 0 | 0 | | | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 15 | 0 | 4 | 0 | | | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 11 | 0 | 3 | 0 | -| | [@elastic/obs-ux-management-team](https://github.com/orgs/elastic/teams/obs-ux-management-team) | - | 131 | 0 | 128 | 0 | +| | [@elastic/obs-ux-management-team](https://github.com/orgs/elastic/teams/obs-ux-management-team) | - | 144 | 0 | 144 | 0 | | | [@elastic/kibana-operations](https://github.com/orgs/elastic/teams/kibana-operations) | - | 20 | 0 | 12 | 0 | | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 102 | 2 | 65 | 1 | | | [@elastic/kibana-operations](https://github.com/orgs/elastic/teams/kibana-operations) | - | 4 | 0 | 2 | 0 | @@ -646,7 +655,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 37 | 0 | 16 | 1 | | | [@elastic/kibana-operations](https://github.com/orgs/elastic/teams/kibana-operations) | - | 2 | 0 | 2 | 0 | | | [@elastic/kibana-operations](https://github.com/orgs/elastic/teams/kibana-operations) | - | 24 | 0 | 14 | 0 | -| | [@elastic/kibana-visualizations](https://github.com/orgs/elastic/teams/kibana-visualizations) | - | 156 | 0 | 152 | 3 | +| | [@elastic/kibana-visualizations](https://github.com/orgs/elastic/teams/kibana-visualizations) | - | 154 | 0 | 151 | 3 | | | [@elastic/obs-ux-logs-team](https://github.com/orgs/elastic/teams/obs-ux-logs-team) | - | 12 | 0 | 12 | 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 | diff --git a/api_docs/presentation_util.mdx b/api_docs/presentation_util.mdx index 6bb413e3682f2..ca1e4ee40d00d 100644 --- a/api_docs/presentation_util.mdx +++ b/api_docs/presentation_util.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/presentationUtil title: "presentationUtil" image: https://source.unsplash.com/400x175/?github description: API docs for the presentationUtil plugin -date: 2023-11-14 +date: 2023-11-16 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 9aa8019145b67..1bda61f7d6011 100644 --- a/api_docs/profiling.mdx +++ b/api_docs/profiling.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/profiling title: "profiling" image: https://source.unsplash.com/400x175/?github description: API docs for the profiling plugin -date: 2023-11-14 +date: 2023-11-16 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 b0e711c72e528..81cc34b894c62 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: 2023-11-14 +date: 2023-11-16 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 dad04211c60af..c150917716ebb 100644 --- a/api_docs/remote_clusters.mdx +++ b/api_docs/remote_clusters.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/remoteClusters title: "remoteClusters" image: https://source.unsplash.com/400x175/?github description: API docs for the remoteClusters plugin -date: 2023-11-14 +date: 2023-11-16 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'remoteClusters'] --- import remoteClustersObj from './remote_clusters.devdocs.json'; diff --git a/api_docs/reporting.devdocs.json b/api_docs/reporting.devdocs.json index 9b536c3ca2f5e..f0f02df91a6e9 100644 --- a/api_docs/reporting.devdocs.json +++ b/api_docs/reporting.devdocs.json @@ -27,17 +27,9 @@ "\nA function that Reporting calls to get the sharing data from the application." ], "signature": [ - "(forShareUrl?: boolean | undefined) => Omit<{ layout?: { id?: ", - { - "pluginId": "screenshotting", - "scope": "common", - "docId": "kibScreenshottingPluginApi", - "section": "def-common.LayoutType", - "text": "LayoutType" - }, - " | undefined; dimensions?: { width: number; height: number; } | undefined; selectors?: Partial<", - "LayoutSelectorDictionary", - "> | undefined; zoom?: number | undefined; } | undefined; objectType: string; title: string; browserTimezone: string; version: string; }, \"version\" | \"browserTimezone\">" + "(forShareUrl?: boolean | undefined) => Omit<", + "BaseParams", + ", \"version\" | \"browserTimezone\">" ], "path": "x-pack/plugins/reporting/public/shared/get_shared_components.tsx", "deprecated": false, @@ -340,363 +332,9 @@ "common": { "classes": [], "functions": [], - "interfaces": [ - { - "parentPluginId": "reporting", - "id": "def-common.BasePayload", - "type": "Interface", - "tags": [ - "deprecated" - ], - "label": "BasePayload", - "description": [], - "signature": [ - { - "pluginId": "reporting", - "scope": "common", - "docId": "kibReportingPluginApi", - "section": "def-common.BasePayload", - "text": "BasePayload" - }, - " extends { layout?: { id?: ", - { - "pluginId": "screenshotting", - "scope": "common", - "docId": "kibScreenshottingPluginApi", - "section": "def-common.LayoutType", - "text": "LayoutType" - }, - " | undefined; dimensions?: { width: number; height: number; } | undefined; selectors?: Partial<", - "LayoutSelectorDictionary", - "> | undefined; zoom?: number | undefined; } | undefined; objectType: string; title: string; browserTimezone: string; version: string; }" - ], - "path": "x-pack/plugins/reporting/common/types/base.ts", - "deprecated": true, - "trackAdoption": false, - "references": [], - "children": [ - { - "parentPluginId": "reporting", - "id": "def-common.BasePayload.headers", - "type": "string", - "tags": [], - "label": "headers", - "description": [], - "path": "x-pack/plugins/reporting/common/types/base.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "reporting", - "id": "def-common.BasePayload.spaceId", - "type": "string", - "tags": [], - "label": "spaceId", - "description": [], - "signature": [ - "string | undefined" - ], - "path": "x-pack/plugins/reporting/common/types/base.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "reporting", - "id": "def-common.BasePayload.isDeprecated", - "type": "CompoundType", - "tags": [], - "label": "isDeprecated", - "description": [], - "signature": [ - "boolean | undefined" - ], - "path": "x-pack/plugins/reporting/common/types/base.ts", - "deprecated": false, - "trackAdoption": false - } - ], - "initialIsOpen": false - }, - { - "parentPluginId": "reporting", - "id": "def-common.BasePayloadV2", - "type": "Interface", - "tags": [], - "label": "BasePayloadV2", - "description": [ - "\nReport job parameters, after they are processed in the request handler." - ], - "signature": [ - { - "pluginId": "reporting", - "scope": "common", - "docId": "kibReportingPluginApi", - "section": "def-common.BasePayloadV2", - "text": "BasePayloadV2" - }, - " extends ", - { - "pluginId": "reporting", - "scope": "common", - "docId": "kibReportingPluginApi", - "section": "def-common.BaseParamsV2", - "text": "BaseParamsV2" - } - ], - "path": "x-pack/plugins/reporting/common/types/base.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "reporting", - "id": "def-common.BasePayloadV2.headers", - "type": "string", - "tags": [], - "label": "headers", - "description": [], - "path": "x-pack/plugins/reporting/common/types/base.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "reporting", - "id": "def-common.BasePayloadV2.spaceId", - "type": "string", - "tags": [], - "label": "spaceId", - "description": [], - "signature": [ - "string | undefined" - ], - "path": "x-pack/plugins/reporting/common/types/base.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "reporting", - "id": "def-common.BasePayloadV2.isDeprecated", - "type": "CompoundType", - "tags": [], - "label": "isDeprecated", - "description": [], - "signature": [ - "boolean | undefined" - ], - "path": "x-pack/plugins/reporting/common/types/base.ts", - "deprecated": false, - "trackAdoption": false - } - ], - "initialIsOpen": false - }, - { - "parentPluginId": "reporting", - "id": "def-common.LocatorParams", - "type": "Interface", - "tags": [], - "label": "LocatorParams", - "description": [], - "signature": [ - { - "pluginId": "reporting", - "scope": "common", - "docId": "kibReportingPluginApi", - "section": "def-common.LocatorParams", - "text": "LocatorParams" - }, - "

" - ], - "path": "x-pack/plugins/reporting/common/types/url.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "reporting", - "id": "def-common.LocatorParams.id", - "type": "string", - "tags": [], - "label": "id", - "description": [], - "path": "x-pack/plugins/reporting/common/types/url.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "reporting", - "id": "def-common.LocatorParams.version", - "type": "string", - "tags": [], - "label": "version", - "description": [ - "\nKibana version used to create the params" - ], - "path": "x-pack/plugins/reporting/common/types/url.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "reporting", - "id": "def-common.LocatorParams.params", - "type": "Uncategorized", - "tags": [], - "label": "params", - "description": [ - "\nData to recreate the user's state in the application" - ], - "signature": [ - "P" - ], - "path": "x-pack/plugins/reporting/common/types/url.ts", - "deprecated": false, - "trackAdoption": false - } - ], - "initialIsOpen": false - } - ], + "interfaces": [], "enums": [], - "misc": [ - { - "parentPluginId": "reporting", - "id": "def-common.BaseParams", - "type": "Type", - "tags": [ - "deprecated" - ], - "label": "BaseParams", - "description": [], - "signature": [ - "{ layout?: { id?: ", - { - "pluginId": "screenshotting", - "scope": "common", - "docId": "kibScreenshottingPluginApi", - "section": "def-common.LayoutType", - "text": "LayoutType" - }, - " | undefined; dimensions?: { width: number; height: number; } | undefined; selectors?: Partial<", - "LayoutSelectorDictionary", - "> | undefined; zoom?: number | undefined; } | undefined; objectType: string; title: string; browserTimezone: string; version: string; }" - ], - "path": "x-pack/plugins/reporting/common/types/base.ts", - "deprecated": true, - "trackAdoption": false, - "references": [], - "initialIsOpen": false - }, - { - "parentPluginId": "reporting", - "id": "def-common.BaseParamsV2", - "type": "Type", - "tags": [], - "label": "BaseParamsV2", - "description": [ - "\nReport job parameters that an application must return from its\ngetSharingData function." - ], - "signature": [ - "{ layout?: { id?: ", - { - "pluginId": "screenshotting", - "scope": "common", - "docId": "kibScreenshottingPluginApi", - "section": "def-common.LayoutType", - "text": "LayoutType" - }, - " | undefined; dimensions?: { width: number; height: number; } | undefined; selectors?: Partial<", - "LayoutSelectorDictionary", - "> | undefined; zoom?: number | undefined; } | undefined; objectType: string; title: string; browserTimezone: string; version: string; } & { locatorParams: ", - { - "pluginId": "reporting", - "scope": "common", - "docId": "kibReportingPluginApi", - "section": "def-common.LocatorParams", - "text": "LocatorParams" - }, - "<", - { - "pluginId": "@kbn/utility-types", - "scope": "common", - "docId": "kibKbnUtilityTypesPluginApi", - "section": "def-common.SerializableRecord", - "text": "SerializableRecord" - }, - ">[]; }" - ], - "path": "x-pack/plugins/reporting/common/types/base.ts", - "deprecated": false, - "trackAdoption": false, - "initialIsOpen": false - }, - { - "parentPluginId": "reporting", - "id": "def-common.JobAppParamsPDF", - "type": "Type", - "tags": [ - "deprecated" - ], - "label": "JobAppParamsPDF", - "description": [], - "signature": [ - "{ isDeprecated?: boolean | undefined; title: string; layout: { id?: ", - { - "pluginId": "screenshotting", - "scope": "common", - "docId": "kibScreenshottingPluginApi", - "section": "def-common.LayoutType", - "text": "LayoutType" - }, - " | undefined; dimensions?: { width: number; height: number; } | undefined; selectors?: Partial<", - "LayoutSelectorDictionary", - "> | undefined; zoom?: number | undefined; }; objectType: string; relativeUrls: string[]; }" - ], - "path": "x-pack/plugins/reporting/common/types/export_types/printable_pdf.ts", - "deprecated": true, - "trackAdoption": false, - "references": [], - "initialIsOpen": false - }, - { - "parentPluginId": "reporting", - "id": "def-common.JobAppParamsPDFV2", - "type": "Type", - "tags": [], - "label": "JobAppParamsPDFV2", - "description": [], - "signature": [ - "{ title: string; layout: { id?: ", - { - "pluginId": "screenshotting", - "scope": "common", - "docId": "kibScreenshottingPluginApi", - "section": "def-common.LayoutType", - "text": "LayoutType" - }, - " | undefined; dimensions?: { width: number; height: number; } | undefined; selectors?: Partial<", - "LayoutSelectorDictionary", - "> | undefined; zoom?: number | undefined; }; locatorParams: ", - { - "pluginId": "reporting", - "scope": "common", - "docId": "kibReportingPluginApi", - "section": "def-common.LocatorParams", - "text": "LocatorParams" - }, - "<", - { - "pluginId": "@kbn/utility-types", - "scope": "common", - "docId": "kibKbnUtilityTypesPluginApi", - "section": "def-common.SerializableRecord", - "text": "SerializableRecord" - }, - ">[]; objectType: string; }" - ], - "path": "x-pack/plugins/reporting/common/types/export_types/printable_pdf_v2.ts", - "deprecated": false, - "trackAdoption": false, - "initialIsOpen": false - } - ], + "misc": [], "objects": [] } } \ No newline at end of file diff --git a/api_docs/reporting.mdx b/api_docs/reporting.mdx index 9c8ef199bf637..1a61297dc8ca1 100644 --- a/api_docs/reporting.mdx +++ b/api_docs/reporting.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/reporting title: "reporting" image: https://source.unsplash.com/400x175/?github description: API docs for the reporting plugin -date: 2023-11-14 +date: 2023-11-16 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'reporting'] --- import reportingObj from './reporting.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 | |-------------------|-----------|------------------------|-----------------| -| 42 | 0 | 22 | 5 | +| 22 | 0 | 6 | 0 | ## Client @@ -36,11 +36,3 @@ Contact [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sh ### Start -## Common - -### Interfaces - - -### Consts, variables and types - - diff --git a/api_docs/rollup.mdx b/api_docs/rollup.mdx index 5efbbe83225ce..72ff879307790 100644 --- a/api_docs/rollup.mdx +++ b/api_docs/rollup.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/rollup title: "rollup" image: https://source.unsplash.com/400x175/?github description: API docs for the rollup plugin -date: 2023-11-14 +date: 2023-11-16 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'rollup'] --- import rollupObj from './rollup.devdocs.json'; diff --git a/api_docs/rule_registry.devdocs.json b/api_docs/rule_registry.devdocs.json index ecf162186c995..6a8f4d39d6857 100644 --- a/api_docs/rule_registry.devdocs.json +++ b/api_docs/rule_registry.devdocs.json @@ -107,7 +107,7 @@ "label": "get", "description": [], "signature": [ - "({ id, index }: GetAlertParams) => Promise> | undefined>" + "({ id, index }: GetAlertParams) => Promise> | undefined>" ], "path": "x-pack/plugins/rule_registry/server/alert_data_client/alerts_client.ts", "deprecated": false, @@ -403,7 +403,7 @@ "SortOptions", "[] | undefined; track_total_hits?: number | boolean | undefined; _source?: string[] | undefined; }) => Promise<", "SearchResponse", - ">, Record>, Record>>" ], @@ -2701,7 +2701,7 @@ "signature": [ "> & OutputOf>>>(request: TSearchRequest) => Promise<", + ", TAlertDoc = Partial> & OutputOf>>>(request: TSearchRequest) => Promise<", { "pluginId": "@kbn/es-types", "scope": "common", @@ -3338,7 +3338,7 @@ "label": "getAlertByAlertUuid", "description": [], "signature": [ - "(alertUuid: string) => Promise> & OutputOf>> | null> | null" + "(alertUuid: string) => Promise> & OutputOf>> | null> | null" ], "path": "x-pack/plugins/rule_registry/server/utils/create_lifecycle_executor.ts", "deprecated": false, @@ -4752,7 +4752,7 @@ "label": "parseTechnicalFields", "description": [], "signature": [ - "(input: unknown, partial?: boolean) => OutputOf>" + "(input: unknown, partial?: boolean) => OutputOf>" ], "path": "x-pack/plugins/rule_registry/common/parse_technical_fields.ts", "deprecated": false, @@ -5128,7 +5128,7 @@ "label": "ParsedTechnicalFields", "description": [], "signature": [ - "{ readonly \"@timestamp\": string; readonly \"kibana.alert.rule.rule_type_id\": string; readonly \"kibana.alert.rule.consumer\": string; readonly \"kibana.alert.instance.id\": string; readonly \"kibana.alert.rule.category\": string; readonly \"kibana.alert.rule.name\": string; readonly \"kibana.alert.rule.producer\": string; readonly \"kibana.alert.rule.revision\": number; readonly \"kibana.alert.rule.uuid\": string; readonly \"kibana.alert.status\": string; readonly \"kibana.alert.uuid\": string; readonly \"kibana.space_ids\": string[]; readonly \"event.action\"?: string | undefined; readonly tags?: string[] | undefined; readonly \"kibana.alert.rule.execution.uuid\"?: string | undefined; readonly \"event.kind\"?: string | undefined; readonly \"kibana.alert.action_group\"?: string | undefined; readonly \"kibana.alert.case_ids\"?: string[] | undefined; readonly \"kibana.alert.duration.us\"?: number | undefined; readonly \"kibana.alert.end\"?: string | undefined; readonly \"kibana.alert.flapping\"?: boolean | undefined; readonly \"kibana.alert.flapping_history\"?: boolean[] | undefined; readonly \"kibana.alert.last_detected\"?: string | undefined; readonly \"kibana.alert.maintenance_window_ids\"?: string[] | undefined; readonly \"kibana.alert.reason\"?: string | undefined; readonly \"kibana.alert.rule.parameters\"?: { [key: string]: unknown; } | undefined; readonly \"kibana.alert.rule.tags\"?: string[] | undefined; readonly \"kibana.alert.start\"?: string | undefined; readonly \"kibana.alert.time_range\"?: unknown; readonly \"kibana.alert.url\"?: string | undefined; readonly \"kibana.alert.workflow_status\"?: string | undefined; readonly \"kibana.alert.workflow_tags\"?: string[] | undefined; readonly \"kibana.version\"?: string | undefined; readonly \"kibana.alert.risk_score\"?: number | undefined; readonly \"kibana.alert.rule.author\"?: string | undefined; readonly \"kibana.alert.rule.created_at\"?: string | undefined; readonly \"kibana.alert.rule.created_by\"?: string | undefined; readonly \"kibana.alert.rule.description\"?: string | undefined; readonly \"kibana.alert.rule.enabled\"?: string | undefined; readonly \"kibana.alert.rule.from\"?: string | undefined; readonly \"kibana.alert.rule.interval\"?: string | undefined; readonly \"kibana.alert.rule.license\"?: string | undefined; readonly \"kibana.alert.rule.note\"?: string | undefined; readonly \"kibana.alert.rule.references\"?: string[] | undefined; readonly \"kibana.alert.rule.rule_id\"?: string | undefined; readonly \"kibana.alert.rule.rule_name_override\"?: string | undefined; readonly \"kibana.alert.rule.to\"?: string | undefined; readonly \"kibana.alert.rule.type\"?: string | undefined; readonly \"kibana.alert.rule.updated_at\"?: string | undefined; readonly \"kibana.alert.rule.updated_by\"?: string | undefined; readonly \"kibana.alert.rule.version\"?: string | undefined; readonly \"kibana.alert.severity\"?: string | undefined; readonly \"kibana.alert.suppression.docs_count\"?: number | undefined; readonly \"kibana.alert.suppression.end\"?: string | undefined; readonly \"kibana.alert.suppression.terms.field\"?: string[] | undefined; readonly \"kibana.alert.suppression.start\"?: string | undefined; readonly \"kibana.alert.suppression.terms.value\"?: string[] | undefined; readonly \"kibana.alert.system_status\"?: string | undefined; readonly \"kibana.alert.workflow_reason\"?: string | undefined; readonly \"kibana.alert.workflow_user\"?: string | undefined; readonly \"ecs.version\"?: string | undefined; }" + "{ readonly \"@timestamp\": string; readonly \"kibana.alert.rule.rule_type_id\": string; readonly \"kibana.alert.rule.consumer\": string; readonly \"kibana.alert.instance.id\": string; readonly \"kibana.alert.rule.category\": string; readonly \"kibana.alert.rule.name\": string; readonly \"kibana.alert.rule.producer\": string; readonly \"kibana.alert.rule.revision\": number; readonly \"kibana.alert.rule.uuid\": string; readonly \"kibana.alert.status\": string; readonly \"kibana.alert.uuid\": string; readonly \"kibana.space_ids\": string[]; readonly \"event.action\"?: string | undefined; readonly tags?: string[] | undefined; readonly \"kibana.alert.rule.execution.uuid\"?: string | undefined; readonly \"event.kind\"?: string | undefined; readonly \"kibana.alert.action_group\"?: string | undefined; readonly \"kibana.alert.case_ids\"?: string[] | undefined; readonly \"kibana.alert.duration.us\"?: number | undefined; readonly \"kibana.alert.end\"?: string | undefined; readonly \"kibana.alert.flapping\"?: boolean | undefined; readonly \"kibana.alert.flapping_history\"?: boolean[] | undefined; readonly \"kibana.alert.last_detected\"?: string | undefined; readonly \"kibana.alert.maintenance_window_ids\"?: string[] | undefined; readonly \"kibana.alert.reason\"?: string | undefined; readonly \"kibana.alert.rule.parameters\"?: { [key: string]: unknown; } | undefined; readonly \"kibana.alert.rule.tags\"?: string[] | undefined; readonly \"kibana.alert.start\"?: string | undefined; readonly \"kibana.alert.time_range\"?: unknown; readonly \"kibana.alert.url\"?: string | undefined; readonly \"kibana.alert.workflow_status\"?: string | undefined; readonly \"kibana.alert.workflow_tags\"?: string[] | undefined; readonly \"kibana.version\"?: string | undefined; readonly \"ecs.version\"?: string | undefined; readonly \"kibana.alert.risk_score\"?: number | undefined; readonly \"kibana.alert.rule.author\"?: string | undefined; readonly \"kibana.alert.rule.created_at\"?: string | undefined; readonly \"kibana.alert.rule.created_by\"?: string | undefined; readonly \"kibana.alert.rule.description\"?: string | undefined; readonly \"kibana.alert.rule.enabled\"?: string | undefined; readonly \"kibana.alert.rule.from\"?: string | undefined; readonly \"kibana.alert.rule.interval\"?: string | undefined; readonly \"kibana.alert.rule.license\"?: string | undefined; readonly \"kibana.alert.rule.note\"?: string | undefined; readonly \"kibana.alert.rule.references\"?: string[] | undefined; readonly \"kibana.alert.rule.rule_id\"?: string | undefined; readonly \"kibana.alert.rule.rule_name_override\"?: string | undefined; readonly \"kibana.alert.rule.to\"?: string | undefined; readonly \"kibana.alert.rule.type\"?: string | undefined; readonly \"kibana.alert.rule.updated_at\"?: string | undefined; readonly \"kibana.alert.rule.updated_by\"?: string | undefined; readonly \"kibana.alert.rule.version\"?: string | undefined; readonly \"kibana.alert.severity\"?: string | undefined; readonly \"kibana.alert.suppression.docs_count\"?: number | undefined; readonly \"kibana.alert.suppression.end\"?: string | undefined; readonly \"kibana.alert.suppression.start\"?: string | undefined; readonly \"kibana.alert.suppression.terms.field\"?: string[] | undefined; readonly \"kibana.alert.suppression.terms.value\"?: string[] | undefined; readonly \"kibana.alert.system_status\"?: string | undefined; readonly \"kibana.alert.workflow_reason\"?: string | undefined; readonly \"kibana.alert.workflow_user\"?: string | undefined; }" ], "path": "x-pack/plugins/rule_registry/common/parse_technical_fields.ts", "deprecated": false, diff --git a/api_docs/rule_registry.mdx b/api_docs/rule_registry.mdx index 063859db7da3e..418f7ce050c39 100644 --- a/api_docs/rule_registry.mdx +++ b/api_docs/rule_registry.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/ruleRegistry title: "ruleRegistry" image: https://source.unsplash.com/400x175/?github description: API docs for the ruleRegistry plugin -date: 2023-11-14 +date: 2023-11-16 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 5c0d7d61d5abb..cc8bb29feeff2 100644 --- a/api_docs/runtime_fields.mdx +++ b/api_docs/runtime_fields.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/runtimeFields title: "runtimeFields" image: https://source.unsplash.com/400x175/?github description: API docs for the runtimeFields plugin -date: 2023-11-14 +date: 2023-11-16 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 359bcbee1c5c1..cca924baeeb7d 100644 --- a/api_docs/saved_objects.mdx +++ b/api_docs/saved_objects.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/savedObjects title: "savedObjects" image: https://source.unsplash.com/400x175/?github description: API docs for the savedObjects plugin -date: 2023-11-14 +date: 2023-11-16 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 fb26d9c500c47..2f098e900ea65 100644 --- a/api_docs/saved_objects_finder.mdx +++ b/api_docs/saved_objects_finder.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/savedObjectsFinder title: "savedObjectsFinder" image: https://source.unsplash.com/400x175/?github description: API docs for the savedObjectsFinder plugin -date: 2023-11-14 +date: 2023-11-16 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'savedObjectsFinder'] --- import savedObjectsFinderObj from './saved_objects_finder.devdocs.json'; diff --git a/api_docs/saved_objects_management.devdocs.json b/api_docs/saved_objects_management.devdocs.json index e8949e085611f..0c087c56c37e4 100644 --- a/api_docs/saved_objects_management.devdocs.json +++ b/api_docs/saved_objects_management.devdocs.json @@ -294,7 +294,7 @@ "label": "euiColumn", "description": [], "signature": [ - "{ prefix?: string | undefined; scope?: string | undefined; id?: string | undefined; defaultValue?: string | number | readonly string[] | undefined; name: React.ReactNode; security?: string | undefined; children?: React.ReactNode; description?: string | undefined; onChange?: React.FormEventHandler | undefined; defaultChecked?: boolean | undefined; suppressContentEditableWarning?: boolean | undefined; suppressHydrationWarning?: boolean | undefined; accessKey?: string | undefined; className?: string | undefined; contentEditable?: \"inherit\" | Booleanish | undefined; contextMenu?: string | undefined; dir?: string | undefined; draggable?: Booleanish | undefined; hidden?: boolean | undefined; lang?: string | undefined; placeholder?: string | undefined; slot?: string | undefined; spellCheck?: Booleanish | undefined; style?: React.CSSProperties | undefined; tabIndex?: number | undefined; title?: string | undefined; translate?: \"no\" | \"yes\" | undefined; radioGroup?: string | undefined; role?: React.AriaRole | undefined; about?: string | undefined; datatype?: string | undefined; inlist?: any; property?: string | undefined; resource?: string | undefined; typeof?: string | undefined; vocab?: string | undefined; autoCapitalize?: string | undefined; autoCorrect?: string | undefined; autoSave?: string | undefined; color?: string | undefined; itemProp?: string | undefined; itemScope?: boolean | undefined; itemType?: string | undefined; itemID?: string | undefined; itemRef?: string | undefined; results?: number | undefined; unselectable?: \"on\" | \"off\" | undefined; inputMode?: \"search\" | \"none\" | \"text\" | \"url\" | \"email\" | \"tel\" | \"numeric\" | \"decimal\" | undefined; is?: string | undefined; 'aria-activedescendant'?: string | undefined; 'aria-atomic'?: Booleanish | undefined; 'aria-autocomplete'?: \"none\" | \"list\" | \"both\" | \"inline\" | undefined; 'aria-busy'?: Booleanish | undefined; 'aria-checked'?: boolean | \"true\" | \"false\" | \"mixed\" | undefined; 'aria-colcount'?: number | undefined; 'aria-colindex'?: number | undefined; 'aria-colspan'?: number | undefined; 'aria-controls'?: string | undefined; 'aria-current'?: boolean | \"page\" | \"date\" | \"true\" | \"false\" | \"location\" | \"time\" | \"step\" | undefined; 'aria-describedby'?: string | undefined; 'aria-details'?: string | undefined; 'aria-disabled'?: Booleanish | undefined; 'aria-dropeffect'?: \"execute\" | \"link\" | \"none\" | \"copy\" | \"move\" | \"popup\" | undefined; 'aria-errormessage'?: string | undefined; 'aria-expanded'?: Booleanish | undefined; 'aria-flowto'?: string | undefined; 'aria-grabbed'?: Booleanish | undefined; 'aria-haspopup'?: boolean | \"true\" | \"false\" | \"grid\" | \"menu\" | \"dialog\" | \"listbox\" | \"tree\" | undefined; 'aria-hidden'?: Booleanish | undefined; 'aria-invalid'?: boolean | \"true\" | \"false\" | \"grammar\" | \"spelling\" | undefined; 'aria-keyshortcuts'?: string | undefined; 'aria-label'?: string | undefined; 'aria-labelledby'?: string | undefined; 'aria-level'?: number | undefined; 'aria-live'?: \"off\" | \"assertive\" | \"polite\" | undefined; 'aria-modal'?: Booleanish | undefined; 'aria-multiline'?: Booleanish | undefined; 'aria-multiselectable'?: Booleanish | undefined; 'aria-orientation'?: \"horizontal\" | \"vertical\" | undefined; 'aria-owns'?: string | undefined; 'aria-placeholder'?: string | undefined; 'aria-posinset'?: number | undefined; 'aria-pressed'?: boolean | \"true\" | \"false\" | \"mixed\" | undefined; 'aria-readonly'?: Booleanish | undefined; 'aria-relevant'?: \"text\" | \"all\" | \"additions\" | \"additions removals\" | \"additions text\" | \"removals\" | \"removals additions\" | \"removals text\" | \"text additions\" | \"text removals\" | undefined; 'aria-required'?: Booleanish | undefined; 'aria-roledescription'?: string | undefined; 'aria-rowcount'?: number | undefined; 'aria-rowindex'?: number | undefined; 'aria-rowspan'?: number | undefined; 'aria-selected'?: Booleanish | undefined; 'aria-setsize'?: number | undefined; 'aria-sort'?: \"none\" | \"other\" | \"ascending\" | \"descending\" | undefined; 'aria-valuemax'?: number | undefined; 'aria-valuemin'?: number | undefined; 'aria-valuenow'?: number | undefined; 'aria-valuetext'?: string | undefined; dangerouslySetInnerHTML?: { __html: string; } | undefined; onCopy?: React.ClipboardEventHandler | undefined; onCopyCapture?: React.ClipboardEventHandler | undefined; onCut?: React.ClipboardEventHandler | undefined; onCutCapture?: React.ClipboardEventHandler | undefined; onPaste?: React.ClipboardEventHandler | undefined; onPasteCapture?: React.ClipboardEventHandler | undefined; onCompositionEnd?: React.CompositionEventHandler | undefined; onCompositionEndCapture?: React.CompositionEventHandler | undefined; onCompositionStart?: React.CompositionEventHandler | undefined; onCompositionStartCapture?: React.CompositionEventHandler | undefined; onCompositionUpdate?: React.CompositionEventHandler | undefined; onCompositionUpdateCapture?: React.CompositionEventHandler | undefined; onFocus?: React.FocusEventHandler | undefined; onFocusCapture?: React.FocusEventHandler | undefined; onBlur?: React.FocusEventHandler | undefined; onBlurCapture?: React.FocusEventHandler | undefined; onChangeCapture?: React.FormEventHandler | undefined; onBeforeInput?: React.FormEventHandler | undefined; onBeforeInputCapture?: React.FormEventHandler | undefined; onInput?: React.FormEventHandler | undefined; onInputCapture?: React.FormEventHandler | undefined; onReset?: React.FormEventHandler | undefined; onResetCapture?: React.FormEventHandler | undefined; onSubmit?: React.FormEventHandler | undefined; onSubmitCapture?: React.FormEventHandler | undefined; onInvalid?: React.FormEventHandler | undefined; onInvalidCapture?: React.FormEventHandler | undefined; onLoad?: React.ReactEventHandler | undefined; onLoadCapture?: React.ReactEventHandler | undefined; onError?: React.ReactEventHandler | undefined; onErrorCapture?: React.ReactEventHandler | undefined; onKeyDown?: React.KeyboardEventHandler | undefined; onKeyDownCapture?: React.KeyboardEventHandler | undefined; onKeyPress?: React.KeyboardEventHandler | undefined; onKeyPressCapture?: React.KeyboardEventHandler | undefined; onKeyUp?: React.KeyboardEventHandler | undefined; onKeyUpCapture?: React.KeyboardEventHandler | undefined; onAbort?: React.ReactEventHandler | undefined; onAbortCapture?: React.ReactEventHandler | undefined; onCanPlay?: React.ReactEventHandler | undefined; onCanPlayCapture?: React.ReactEventHandler | undefined; onCanPlayThrough?: React.ReactEventHandler | undefined; onCanPlayThroughCapture?: React.ReactEventHandler | undefined; onDurationChange?: React.ReactEventHandler | undefined; onDurationChangeCapture?: React.ReactEventHandler | undefined; onEmptied?: React.ReactEventHandler | undefined; onEmptiedCapture?: React.ReactEventHandler | undefined; onEncrypted?: React.ReactEventHandler | undefined; onEncryptedCapture?: React.ReactEventHandler | undefined; onEnded?: React.ReactEventHandler | undefined; onEndedCapture?: React.ReactEventHandler | undefined; onLoadedData?: React.ReactEventHandler | undefined; onLoadedDataCapture?: React.ReactEventHandler | undefined; onLoadedMetadata?: React.ReactEventHandler | undefined; onLoadedMetadataCapture?: React.ReactEventHandler | undefined; onLoadStart?: React.ReactEventHandler | undefined; onLoadStartCapture?: React.ReactEventHandler | undefined; onPause?: React.ReactEventHandler | undefined; onPauseCapture?: React.ReactEventHandler | undefined; onPlay?: React.ReactEventHandler | undefined; onPlayCapture?: React.ReactEventHandler | undefined; onPlaying?: React.ReactEventHandler | undefined; onPlayingCapture?: React.ReactEventHandler | undefined; onProgress?: React.ReactEventHandler | undefined; onProgressCapture?: React.ReactEventHandler | undefined; onRateChange?: React.ReactEventHandler | undefined; onRateChangeCapture?: React.ReactEventHandler | undefined; onSeeked?: React.ReactEventHandler | undefined; onSeekedCapture?: React.ReactEventHandler | undefined; onSeeking?: React.ReactEventHandler | undefined; onSeekingCapture?: React.ReactEventHandler | undefined; onStalled?: React.ReactEventHandler | undefined; onStalledCapture?: React.ReactEventHandler | undefined; onSuspend?: React.ReactEventHandler | undefined; onSuspendCapture?: React.ReactEventHandler | undefined; onTimeUpdate?: React.ReactEventHandler | undefined; onTimeUpdateCapture?: React.ReactEventHandler | undefined; onVolumeChange?: React.ReactEventHandler | undefined; onVolumeChangeCapture?: React.ReactEventHandler | undefined; onWaiting?: React.ReactEventHandler | undefined; onWaitingCapture?: React.ReactEventHandler | undefined; onAuxClick?: React.MouseEventHandler | undefined; onAuxClickCapture?: React.MouseEventHandler | undefined; onClick?: React.MouseEventHandler | undefined; onClickCapture?: React.MouseEventHandler | undefined; onContextMenu?: React.MouseEventHandler | undefined; onContextMenuCapture?: React.MouseEventHandler | undefined; onDoubleClick?: React.MouseEventHandler | undefined; onDoubleClickCapture?: React.MouseEventHandler | undefined; onDrag?: React.DragEventHandler | undefined; onDragCapture?: React.DragEventHandler | undefined; onDragEnd?: React.DragEventHandler | undefined; onDragEndCapture?: React.DragEventHandler | undefined; onDragEnter?: React.DragEventHandler | undefined; onDragEnterCapture?: React.DragEventHandler | undefined; onDragExit?: React.DragEventHandler | undefined; onDragExitCapture?: React.DragEventHandler | undefined; onDragLeave?: React.DragEventHandler | undefined; onDragLeaveCapture?: React.DragEventHandler | undefined; onDragOver?: React.DragEventHandler | undefined; onDragOverCapture?: React.DragEventHandler | undefined; onDragStart?: React.DragEventHandler | undefined; onDragStartCapture?: React.DragEventHandler | undefined; onDrop?: React.DragEventHandler | undefined; onDropCapture?: React.DragEventHandler | undefined; onMouseDown?: React.MouseEventHandler | undefined; onMouseDownCapture?: React.MouseEventHandler | undefined; onMouseEnter?: React.MouseEventHandler | undefined; onMouseLeave?: React.MouseEventHandler | undefined; onMouseMove?: React.MouseEventHandler | undefined; onMouseMoveCapture?: React.MouseEventHandler | undefined; onMouseOut?: React.MouseEventHandler | undefined; onMouseOutCapture?: React.MouseEventHandler | undefined; onMouseOver?: React.MouseEventHandler | undefined; onMouseOverCapture?: React.MouseEventHandler | undefined; onMouseUp?: React.MouseEventHandler | undefined; onMouseUpCapture?: React.MouseEventHandler | undefined; onSelect?: React.ReactEventHandler | undefined; onSelectCapture?: React.ReactEventHandler | undefined; onTouchCancel?: React.TouchEventHandler | undefined; onTouchCancelCapture?: React.TouchEventHandler | undefined; onTouchEnd?: React.TouchEventHandler | undefined; onTouchEndCapture?: React.TouchEventHandler | undefined; onTouchMove?: React.TouchEventHandler | undefined; onTouchMoveCapture?: React.TouchEventHandler | undefined; onTouchStart?: React.TouchEventHandler | undefined; onTouchStartCapture?: React.TouchEventHandler | undefined; onPointerDown?: React.PointerEventHandler | undefined; onPointerDownCapture?: React.PointerEventHandler | undefined; onPointerMove?: React.PointerEventHandler | undefined; onPointerMoveCapture?: React.PointerEventHandler | undefined; onPointerUp?: React.PointerEventHandler | undefined; onPointerUpCapture?: React.PointerEventHandler | undefined; onPointerCancel?: React.PointerEventHandler | undefined; onPointerCancelCapture?: React.PointerEventHandler | undefined; onPointerEnter?: React.PointerEventHandler | undefined; onPointerEnterCapture?: React.PointerEventHandler | undefined; onPointerLeave?: React.PointerEventHandler | undefined; onPointerLeaveCapture?: React.PointerEventHandler | undefined; onPointerOver?: React.PointerEventHandler | undefined; onPointerOverCapture?: React.PointerEventHandler | undefined; onPointerOut?: React.PointerEventHandler | undefined; onPointerOutCapture?: React.PointerEventHandler | undefined; onGotPointerCapture?: React.PointerEventHandler | undefined; onGotPointerCaptureCapture?: React.PointerEventHandler | undefined; onLostPointerCapture?: React.PointerEventHandler | undefined; onLostPointerCaptureCapture?: React.PointerEventHandler | undefined; onScroll?: React.UIEventHandler | undefined; onScrollCapture?: React.UIEventHandler | undefined; onWheel?: React.WheelEventHandler | undefined; onWheelCapture?: React.WheelEventHandler | undefined; onAnimationStart?: React.AnimationEventHandler | undefined; onAnimationStartCapture?: React.AnimationEventHandler | undefined; onAnimationEnd?: React.AnimationEventHandler | undefined; onAnimationEndCapture?: React.AnimationEventHandler | undefined; onAnimationIteration?: React.AnimationEventHandler | undefined; onAnimationIterationCapture?: React.AnimationEventHandler | undefined; onTransitionEnd?: React.TransitionEventHandler | undefined; onTransitionEndCapture?: React.TransitionEventHandler | undefined; 'data-test-subj'?: string | undefined; css?: ", + "{ prefix?: string | undefined; scope?: string | undefined; id?: string | undefined; defaultValue?: string | number | readonly string[] | undefined; name: React.ReactNode; security?: string | undefined; children?: React.ReactNode; description?: string | undefined; onChange?: React.FormEventHandler | undefined; defaultChecked?: boolean | undefined; suppressContentEditableWarning?: boolean | undefined; suppressHydrationWarning?: boolean | undefined; accessKey?: string | undefined; className?: string | undefined; contentEditable?: \"inherit\" | Booleanish | undefined; contextMenu?: string | undefined; dir?: string | undefined; draggable?: Booleanish | undefined; hidden?: boolean | undefined; lang?: string | undefined; placeholder?: string | undefined; slot?: string | undefined; spellCheck?: Booleanish | undefined; style?: React.CSSProperties | undefined; tabIndex?: number | undefined; title?: string | undefined; translate?: \"no\" | \"yes\" | undefined; radioGroup?: string | undefined; role?: React.AriaRole | undefined; about?: string | undefined; datatype?: string | undefined; inlist?: any; property?: string | undefined; resource?: string | undefined; typeof?: string | undefined; vocab?: string | undefined; autoCapitalize?: string | undefined; autoCorrect?: string | undefined; autoSave?: string | undefined; color?: string | undefined; itemProp?: string | undefined; itemScope?: boolean | undefined; itemType?: string | undefined; itemID?: string | undefined; itemRef?: string | undefined; results?: number | undefined; unselectable?: \"on\" | \"off\" | undefined; inputMode?: \"search\" | \"none\" | \"text\" | \"url\" | \"email\" | \"tel\" | \"numeric\" | \"decimal\" | undefined; is?: string | undefined; 'aria-activedescendant'?: string | undefined; 'aria-atomic'?: Booleanish | undefined; 'aria-autocomplete'?: \"none\" | \"list\" | \"both\" | \"inline\" | undefined; 'aria-busy'?: Booleanish | undefined; 'aria-checked'?: boolean | \"true\" | \"false\" | \"mixed\" | undefined; 'aria-colcount'?: number | undefined; 'aria-colindex'?: number | undefined; 'aria-colspan'?: number | undefined; 'aria-controls'?: string | undefined; 'aria-current'?: boolean | \"page\" | \"date\" | \"location\" | \"true\" | \"false\" | \"time\" | \"step\" | undefined; 'aria-describedby'?: string | undefined; 'aria-details'?: string | undefined; 'aria-disabled'?: Booleanish | undefined; 'aria-dropeffect'?: \"execute\" | \"link\" | \"none\" | \"copy\" | \"move\" | \"popup\" | undefined; 'aria-errormessage'?: string | undefined; 'aria-expanded'?: Booleanish | undefined; 'aria-flowto'?: string | undefined; 'aria-grabbed'?: Booleanish | undefined; 'aria-haspopup'?: boolean | \"true\" | \"false\" | \"grid\" | \"menu\" | \"dialog\" | \"listbox\" | \"tree\" | undefined; 'aria-hidden'?: Booleanish | undefined; 'aria-invalid'?: boolean | \"true\" | \"false\" | \"grammar\" | \"spelling\" | undefined; 'aria-keyshortcuts'?: string | undefined; 'aria-label'?: string | undefined; 'aria-labelledby'?: string | undefined; 'aria-level'?: number | undefined; 'aria-live'?: \"off\" | \"assertive\" | \"polite\" | undefined; 'aria-modal'?: Booleanish | undefined; 'aria-multiline'?: Booleanish | undefined; 'aria-multiselectable'?: Booleanish | undefined; 'aria-orientation'?: \"horizontal\" | \"vertical\" | undefined; 'aria-owns'?: string | undefined; 'aria-placeholder'?: string | undefined; 'aria-posinset'?: number | undefined; 'aria-pressed'?: boolean | \"true\" | \"false\" | \"mixed\" | undefined; 'aria-readonly'?: Booleanish | undefined; 'aria-relevant'?: \"text\" | \"all\" | \"additions\" | \"additions removals\" | \"additions text\" | \"removals\" | \"removals additions\" | \"removals text\" | \"text additions\" | \"text removals\" | undefined; 'aria-required'?: Booleanish | undefined; 'aria-roledescription'?: string | undefined; 'aria-rowcount'?: number | undefined; 'aria-rowindex'?: number | undefined; 'aria-rowspan'?: number | undefined; 'aria-selected'?: Booleanish | undefined; 'aria-setsize'?: number | undefined; 'aria-sort'?: \"none\" | \"other\" | \"ascending\" | \"descending\" | undefined; 'aria-valuemax'?: number | undefined; 'aria-valuemin'?: number | undefined; 'aria-valuenow'?: number | undefined; 'aria-valuetext'?: string | undefined; dangerouslySetInnerHTML?: { __html: string; } | undefined; onCopy?: React.ClipboardEventHandler | undefined; onCopyCapture?: React.ClipboardEventHandler | undefined; onCut?: React.ClipboardEventHandler | undefined; onCutCapture?: React.ClipboardEventHandler | undefined; onPaste?: React.ClipboardEventHandler | undefined; onPasteCapture?: React.ClipboardEventHandler | undefined; onCompositionEnd?: React.CompositionEventHandler | undefined; onCompositionEndCapture?: React.CompositionEventHandler | undefined; onCompositionStart?: React.CompositionEventHandler | undefined; onCompositionStartCapture?: React.CompositionEventHandler | undefined; onCompositionUpdate?: React.CompositionEventHandler | undefined; onCompositionUpdateCapture?: React.CompositionEventHandler | undefined; onFocus?: React.FocusEventHandler | undefined; onFocusCapture?: React.FocusEventHandler | undefined; onBlur?: React.FocusEventHandler | undefined; onBlurCapture?: React.FocusEventHandler | undefined; onChangeCapture?: React.FormEventHandler | undefined; onBeforeInput?: React.FormEventHandler | undefined; onBeforeInputCapture?: React.FormEventHandler | undefined; onInput?: React.FormEventHandler | undefined; onInputCapture?: React.FormEventHandler | undefined; onReset?: React.FormEventHandler | undefined; onResetCapture?: React.FormEventHandler | undefined; onSubmit?: React.FormEventHandler | undefined; onSubmitCapture?: React.FormEventHandler | undefined; onInvalid?: React.FormEventHandler | undefined; onInvalidCapture?: React.FormEventHandler | undefined; onLoad?: React.ReactEventHandler | undefined; onLoadCapture?: React.ReactEventHandler | undefined; onError?: React.ReactEventHandler | undefined; onErrorCapture?: React.ReactEventHandler | undefined; onKeyDown?: React.KeyboardEventHandler | undefined; onKeyDownCapture?: React.KeyboardEventHandler | undefined; onKeyPress?: React.KeyboardEventHandler | undefined; onKeyPressCapture?: React.KeyboardEventHandler | undefined; onKeyUp?: React.KeyboardEventHandler | undefined; onKeyUpCapture?: React.KeyboardEventHandler | undefined; onAbort?: React.ReactEventHandler | undefined; onAbortCapture?: React.ReactEventHandler | undefined; onCanPlay?: React.ReactEventHandler | undefined; onCanPlayCapture?: React.ReactEventHandler | undefined; onCanPlayThrough?: React.ReactEventHandler | undefined; onCanPlayThroughCapture?: React.ReactEventHandler | undefined; onDurationChange?: React.ReactEventHandler | undefined; onDurationChangeCapture?: React.ReactEventHandler | undefined; onEmptied?: React.ReactEventHandler | undefined; onEmptiedCapture?: React.ReactEventHandler | undefined; onEncrypted?: React.ReactEventHandler | undefined; onEncryptedCapture?: React.ReactEventHandler | undefined; onEnded?: React.ReactEventHandler | undefined; onEndedCapture?: React.ReactEventHandler | undefined; onLoadedData?: React.ReactEventHandler | undefined; onLoadedDataCapture?: React.ReactEventHandler | undefined; onLoadedMetadata?: React.ReactEventHandler | undefined; onLoadedMetadataCapture?: React.ReactEventHandler | undefined; onLoadStart?: React.ReactEventHandler | undefined; onLoadStartCapture?: React.ReactEventHandler | undefined; onPause?: React.ReactEventHandler | undefined; onPauseCapture?: React.ReactEventHandler | undefined; onPlay?: React.ReactEventHandler | undefined; onPlayCapture?: React.ReactEventHandler | undefined; onPlaying?: React.ReactEventHandler | undefined; onPlayingCapture?: React.ReactEventHandler | undefined; onProgress?: React.ReactEventHandler | undefined; onProgressCapture?: React.ReactEventHandler | undefined; onRateChange?: React.ReactEventHandler | undefined; onRateChangeCapture?: React.ReactEventHandler | undefined; onSeeked?: React.ReactEventHandler | undefined; onSeekedCapture?: React.ReactEventHandler | undefined; onSeeking?: React.ReactEventHandler | undefined; onSeekingCapture?: React.ReactEventHandler | undefined; onStalled?: React.ReactEventHandler | undefined; onStalledCapture?: React.ReactEventHandler | undefined; onSuspend?: React.ReactEventHandler | undefined; onSuspendCapture?: React.ReactEventHandler | undefined; onTimeUpdate?: React.ReactEventHandler | undefined; onTimeUpdateCapture?: React.ReactEventHandler | undefined; onVolumeChange?: React.ReactEventHandler | undefined; onVolumeChangeCapture?: React.ReactEventHandler | undefined; onWaiting?: React.ReactEventHandler | undefined; onWaitingCapture?: React.ReactEventHandler | undefined; onAuxClick?: React.MouseEventHandler | undefined; onAuxClickCapture?: React.MouseEventHandler | undefined; onClick?: React.MouseEventHandler | undefined; onClickCapture?: React.MouseEventHandler | undefined; onContextMenu?: React.MouseEventHandler | undefined; onContextMenuCapture?: React.MouseEventHandler | undefined; onDoubleClick?: React.MouseEventHandler | undefined; onDoubleClickCapture?: React.MouseEventHandler | undefined; onDrag?: React.DragEventHandler | undefined; onDragCapture?: React.DragEventHandler | undefined; onDragEnd?: React.DragEventHandler | undefined; onDragEndCapture?: React.DragEventHandler | undefined; onDragEnter?: React.DragEventHandler | undefined; onDragEnterCapture?: React.DragEventHandler | undefined; onDragExit?: React.DragEventHandler | undefined; onDragExitCapture?: React.DragEventHandler | undefined; onDragLeave?: React.DragEventHandler | undefined; onDragLeaveCapture?: React.DragEventHandler | undefined; onDragOver?: React.DragEventHandler | undefined; onDragOverCapture?: React.DragEventHandler | undefined; onDragStart?: React.DragEventHandler | undefined; onDragStartCapture?: React.DragEventHandler | undefined; onDrop?: React.DragEventHandler | undefined; onDropCapture?: React.DragEventHandler | undefined; onMouseDown?: React.MouseEventHandler | undefined; onMouseDownCapture?: React.MouseEventHandler | undefined; onMouseEnter?: React.MouseEventHandler | undefined; onMouseLeave?: React.MouseEventHandler | undefined; onMouseMove?: React.MouseEventHandler | undefined; onMouseMoveCapture?: React.MouseEventHandler | undefined; onMouseOut?: React.MouseEventHandler | undefined; onMouseOutCapture?: React.MouseEventHandler | undefined; onMouseOver?: React.MouseEventHandler | undefined; onMouseOverCapture?: React.MouseEventHandler | undefined; onMouseUp?: React.MouseEventHandler | undefined; onMouseUpCapture?: React.MouseEventHandler | undefined; onSelect?: React.ReactEventHandler | undefined; onSelectCapture?: React.ReactEventHandler | undefined; onTouchCancel?: React.TouchEventHandler | undefined; onTouchCancelCapture?: React.TouchEventHandler | undefined; onTouchEnd?: React.TouchEventHandler | undefined; onTouchEndCapture?: React.TouchEventHandler | undefined; onTouchMove?: React.TouchEventHandler | undefined; onTouchMoveCapture?: React.TouchEventHandler | undefined; onTouchStart?: React.TouchEventHandler | undefined; onTouchStartCapture?: React.TouchEventHandler | undefined; onPointerDown?: React.PointerEventHandler | undefined; onPointerDownCapture?: React.PointerEventHandler | undefined; onPointerMove?: React.PointerEventHandler | undefined; onPointerMoveCapture?: React.PointerEventHandler | undefined; onPointerUp?: React.PointerEventHandler | undefined; onPointerUpCapture?: React.PointerEventHandler | undefined; onPointerCancel?: React.PointerEventHandler | undefined; onPointerCancelCapture?: React.PointerEventHandler | undefined; onPointerEnter?: React.PointerEventHandler | undefined; onPointerEnterCapture?: React.PointerEventHandler | undefined; onPointerLeave?: React.PointerEventHandler | undefined; onPointerLeaveCapture?: React.PointerEventHandler | undefined; onPointerOver?: React.PointerEventHandler | undefined; onPointerOverCapture?: React.PointerEventHandler | undefined; onPointerOut?: React.PointerEventHandler | undefined; onPointerOutCapture?: React.PointerEventHandler | undefined; onGotPointerCapture?: React.PointerEventHandler | undefined; onGotPointerCaptureCapture?: React.PointerEventHandler | undefined; onLostPointerCapture?: React.PointerEventHandler | undefined; onLostPointerCaptureCapture?: React.PointerEventHandler | undefined; onScroll?: React.UIEventHandler | undefined; onScrollCapture?: React.UIEventHandler | undefined; onWheel?: React.WheelEventHandler | undefined; onWheelCapture?: React.WheelEventHandler | undefined; onAnimationStart?: React.AnimationEventHandler | undefined; onAnimationStartCapture?: React.AnimationEventHandler | undefined; onAnimationEnd?: React.AnimationEventHandler | undefined; onAnimationEndCapture?: React.AnimationEventHandler | undefined; onAnimationIteration?: React.AnimationEventHandler | undefined; onAnimationIterationCapture?: React.AnimationEventHandler | undefined; onTransitionEnd?: React.TransitionEventHandler | undefined; onTransitionEndCapture?: React.TransitionEventHandler | undefined; 'data-test-subj'?: string | undefined; css?: ", "Interpolation", "<", "Theme", diff --git a/api_docs/saved_objects_management.mdx b/api_docs/saved_objects_management.mdx index cd5e4681fa4eb..565f6dfe7ef38 100644 --- a/api_docs/saved_objects_management.mdx +++ b/api_docs/saved_objects_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/savedObjectsManagement title: "savedObjectsManagement" image: https://source.unsplash.com/400x175/?github description: API docs for the savedObjectsManagement plugin -date: 2023-11-14 +date: 2023-11-16 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 67575a8f5cf8f..0ff75ff009637 100644 --- a/api_docs/saved_objects_tagging.mdx +++ b/api_docs/saved_objects_tagging.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/savedObjectsTagging title: "savedObjectsTagging" image: https://source.unsplash.com/400x175/?github description: API docs for the savedObjectsTagging plugin -date: 2023-11-14 +date: 2023-11-16 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 01871a23bdaeb..9639090cb1656 100644 --- a/api_docs/saved_objects_tagging_oss.mdx +++ b/api_docs/saved_objects_tagging_oss.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/savedObjectsTaggingOss title: "savedObjectsTaggingOss" image: https://source.unsplash.com/400x175/?github description: API docs for the savedObjectsTaggingOss plugin -date: 2023-11-14 +date: 2023-11-16 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 4a436210cf72c..4981df336cae1 100644 --- a/api_docs/saved_search.mdx +++ b/api_docs/saved_search.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/savedSearch title: "savedSearch" image: https://source.unsplash.com/400x175/?github description: API docs for the savedSearch plugin -date: 2023-11-14 +date: 2023-11-16 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 983ced12b53d9..8b9513867ef46 100644 --- a/api_docs/screenshot_mode.mdx +++ b/api_docs/screenshot_mode.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/screenshotMode title: "screenshotMode" image: https://source.unsplash.com/400x175/?github description: API docs for the screenshotMode plugin -date: 2023-11-14 +date: 2023-11-16 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'screenshotMode'] --- import screenshotModeObj from './screenshot_mode.devdocs.json'; diff --git a/api_docs/screenshotting.devdocs.json b/api_docs/screenshotting.devdocs.json index 64c08e6ab7e51..a28a526b04998 100644 --- a/api_docs/screenshotting.devdocs.json +++ b/api_docs/screenshotting.devdocs.json @@ -488,7 +488,88 @@ "common": { "classes": [], "functions": [], - "interfaces": [], + "interfaces": [ + { + "parentPluginId": "screenshotting", + "id": "def-common.PerformanceMetrics", + "type": "Interface", + "tags": [], + "label": "PerformanceMetrics", + "description": [ + "\nCollected performance metrics during a screenshotting session." + ], + "path": "x-pack/plugins/screenshotting/common/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "screenshotting", + "id": "def-common.PerformanceMetrics.cpu", + "type": "number", + "tags": [], + "label": "cpu", + "description": [ + "\nThe percentage of CPU time spent by the browser divided by number or cores." + ], + "signature": [ + "number | undefined" + ], + "path": "x-pack/plugins/screenshotting/common/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "screenshotting", + "id": "def-common.PerformanceMetrics.cpuInPercentage", + "type": "number", + "tags": [], + "label": "cpuInPercentage", + "description": [ + "\nThe percentage of CPU in percent untis." + ], + "signature": [ + "number | undefined" + ], + "path": "x-pack/plugins/screenshotting/common/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "screenshotting", + "id": "def-common.PerformanceMetrics.memory", + "type": "number", + "tags": [], + "label": "memory", + "description": [ + "\nThe total amount of memory used by the browser." + ], + "signature": [ + "number | undefined" + ], + "path": "x-pack/plugins/screenshotting/common/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "screenshotting", + "id": "def-common.PerformanceMetrics.memoryInMegabytes", + "type": "number", + "tags": [], + "label": "memoryInMegabytes", + "description": [ + "\nThe total amount of memory used by the browser in megabytes." + ], + "signature": [ + "number | undefined" + ], + "path": "x-pack/plugins/screenshotting/common/types.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + } + ], "enums": [], "misc": [ { @@ -538,7 +619,7 @@ "\nSupported layout types." ], "signature": [ - "\"canvas\" | \"preserve_layout\" | \"print\"" + "\"canvas\" | \"print\" | \"preserve_layout\"" ], "path": "x-pack/plugins/screenshotting/common/layout.ts", "deprecated": false, diff --git a/api_docs/screenshotting.mdx b/api_docs/screenshotting.mdx index b0d989619e999..a70c69c91deec 100644 --- a/api_docs/screenshotting.mdx +++ b/api_docs/screenshotting.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/screenshotting title: "screenshotting" image: https://source.unsplash.com/400x175/?github description: API docs for the screenshotting plugin -date: 2023-11-14 +date: 2023-11-16 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'screenshotting'] --- import screenshottingObj from './screenshotting.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/kibana-reporting-services](https://github.com/orgs/elastic/tea | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 27 | 0 | 8 | 5 | +| 32 | 0 | 8 | 4 | ## Client @@ -41,6 +41,9 @@ Contact [@elastic/kibana-reporting-services](https://github.com/orgs/elastic/tea ## Common +### Interfaces + + ### Consts, variables and types diff --git a/api_docs/security.mdx b/api_docs/security.mdx index db7d166313d04..febe88375ef3a 100644 --- a/api_docs/security.mdx +++ b/api_docs/security.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/security title: "security" image: https://source.unsplash.com/400x175/?github description: API docs for the security plugin -date: 2023-11-14 +date: 2023-11-16 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 ce5c223dae65c..bc3ffdf380911 100644 --- a/api_docs/security_solution.mdx +++ b/api_docs/security_solution.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/securitySolution title: "securitySolution" image: https://source.unsplash.com/400x175/?github description: API docs for the securitySolution plugin -date: 2023-11-14 +date: 2023-11-16 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 6e9de50cb478d..b58dafce91a15 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: 2023-11-14 +date: 2023-11-16 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 14e63a5424534..cf9ec5b91aaba 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: 2023-11-14 +date: 2023-11-16 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 44a707b74a070..fe1cd09d3cf8d 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: 2023-11-14 +date: 2023-11-16 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 9d2c351c55d1f..0ae7995397c18 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: 2023-11-14 +date: 2023-11-16 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 3f7a53a248344..fe91d628cb1a0 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: 2023-11-14 +date: 2023-11-16 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 bae2f6cca987f..ac01cb7764571 100644 --- a/api_docs/session_view.mdx +++ b/api_docs/session_view.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/sessionView title: "sessionView" image: https://source.unsplash.com/400x175/?github description: API docs for the sessionView plugin -date: 2023-11-14 +date: 2023-11-16 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 acbb0d65bf639..49683b402acb9 100644 --- a/api_docs/share.mdx +++ b/api_docs/share.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/share title: "share" image: https://source.unsplash.com/400x175/?github description: API docs for the share plugin -date: 2023-11-14 +date: 2023-11-16 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'share'] --- import shareObj from './share.devdocs.json'; diff --git a/api_docs/snapshot_restore.mdx b/api_docs/snapshot_restore.mdx index d2e104d1fef72..324c3f8ade86e 100644 --- a/api_docs/snapshot_restore.mdx +++ b/api_docs/snapshot_restore.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/snapshotRestore title: "snapshotRestore" image: https://source.unsplash.com/400x175/?github description: API docs for the snapshotRestore plugin -date: 2023-11-14 +date: 2023-11-16 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 603ec76c27507..948e23e6a61bc 100644 --- a/api_docs/spaces.mdx +++ b/api_docs/spaces.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/spaces title: "spaces" image: https://source.unsplash.com/400x175/?github description: API docs for the spaces plugin -date: 2023-11-14 +date: 2023-11-16 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 8a5a7f6948232..7207b47ea96d5 100644 --- a/api_docs/stack_alerts.mdx +++ b/api_docs/stack_alerts.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/stackAlerts title: "stackAlerts" image: https://source.unsplash.com/400x175/?github description: API docs for the stackAlerts plugin -date: 2023-11-14 +date: 2023-11-16 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 123e5f8ff79da..80b732da8644a 100644 --- a/api_docs/stack_connectors.mdx +++ b/api_docs/stack_connectors.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/stackConnectors title: "stackConnectors" image: https://source.unsplash.com/400x175/?github description: API docs for the stackConnectors plugin -date: 2023-11-14 +date: 2023-11-16 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'stackConnectors'] --- import stackConnectorsObj from './stack_connectors.devdocs.json'; diff --git a/api_docs/task_manager.devdocs.json b/api_docs/task_manager.devdocs.json index 620d48af005c2..2bc531bde5295 100644 --- a/api_docs/task_manager.devdocs.json +++ b/api_docs/task_manager.devdocs.json @@ -345,7 +345,13 @@ "description": [], "signature": [ "(error: Error) => ", - "DecoratedError" + { + "pluginId": "taskManager", + "scope": "server", + "docId": "kibTaskManagerPluginApi", + "section": "def-server.DecoratedError", + "text": "DecoratedError" + } ], "path": "x-pack/plugins/task_manager/server/task_running/errors.ts", "deprecated": false, @@ -370,6 +376,75 @@ "returnComment": [], "initialIsOpen": false }, + { + "parentPluginId": "taskManager", + "id": "def-server.createTaskRunError", + "type": "Function", + "tags": [], + "label": "createTaskRunError", + "description": [], + "signature": [ + "(error: Error, errorSource: ", + { + "pluginId": "taskManager", + "scope": "server", + "docId": "kibTaskManagerPluginApi", + "section": "def-server.TaskErrorSource", + "text": "TaskErrorSource" + }, + ") => ", + { + "pluginId": "taskManager", + "scope": "server", + "docId": "kibTaskManagerPluginApi", + "section": "def-server.DecoratedError", + "text": "DecoratedError" + } + ], + "path": "x-pack/plugins/task_manager/server/task_running/errors.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "taskManager", + "id": "def-server.createTaskRunError.$1", + "type": "Object", + "tags": [], + "label": "error", + "description": [], + "signature": [ + "Error" + ], + "path": "x-pack/plugins/task_manager/server/task_running/errors.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "taskManager", + "id": "def-server.createTaskRunError.$2", + "type": "Enum", + "tags": [], + "label": "errorSource", + "description": [], + "signature": [ + { + "pluginId": "taskManager", + "scope": "server", + "docId": "kibTaskManagerPluginApi", + "section": "def-server.TaskErrorSource", + "text": "TaskErrorSource" + } + ], + "path": "x-pack/plugins/task_manager/server/task_running/errors.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [], + "initialIsOpen": false + }, { "parentPluginId": "taskManager", "id": "def-server.isEphemeralTaskRejectedDueToCapacityError", @@ -415,7 +490,13 @@ "description": [], "signature": [ "(error: Error | ", - "DecoratedError", + { + "pluginId": "taskManager", + "scope": "server", + "docId": "kibTaskManagerPluginApi", + "section": "def-server.DecoratedError", + "text": "DecoratedError" + }, ") => boolean" ], "path": "x-pack/plugins/task_manager/server/task_running/errors.ts", @@ -431,7 +512,13 @@ "description": [], "signature": [ "Error | ", - "DecoratedError" + { + "pluginId": "taskManager", + "scope": "server", + "docId": "kibTaskManagerPluginApi", + "section": "def-server.DecoratedError", + "text": "DecoratedError" + } ], "path": "x-pack/plugins/task_manager/server/task_running/errors.ts", "deprecated": false, @@ -451,7 +538,13 @@ "description": [], "signature": [ "(error: Error | ", - "DecoratedError", + { + "pluginId": "taskManager", + "scope": "server", + "docId": "kibTaskManagerPluginApi", + "section": "def-server.DecoratedError", + "text": "DecoratedError" + }, ") => boolean" ], "path": "x-pack/plugins/task_manager/server/task_running/errors.ts", @@ -467,7 +560,13 @@ "description": [], "signature": [ "Error | ", - "DecoratedError" + { + "pluginId": "taskManager", + "scope": "server", + "docId": "kibTaskManagerPluginApi", + "section": "def-server.DecoratedError", + "text": "DecoratedError" + } ], "path": "x-pack/plugins/task_manager/server/task_running/errors.ts", "deprecated": false, @@ -534,7 +633,15 @@ "label": "throwUnrecoverableError", "description": [], "signature": [ - "(error: Error) => void" + "(error: Error, errorSource: ", + { + "pluginId": "taskManager", + "scope": "server", + "docId": "kibTaskManagerPluginApi", + "section": "def-server.TaskErrorSource", + "text": "TaskErrorSource" + }, + ") => void" ], "path": "x-pack/plugins/task_manager/server/task_running/errors.ts", "deprecated": false, @@ -554,6 +661,27 @@ "deprecated": false, "trackAdoption": false, "isRequired": true + }, + { + "parentPluginId": "taskManager", + "id": "def-server.throwUnrecoverableError.$2", + "type": "Enum", + "tags": [], + "label": "errorSource", + "description": [], + "signature": [ + { + "pluginId": "taskManager", + "scope": "server", + "docId": "kibTaskManagerPluginApi", + "section": "def-server.TaskErrorSource", + "text": "TaskErrorSource" + } + ], + "path": "x-pack/plugins/task_manager/server/task_running/errors.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true } ], "returnComment": [], @@ -834,6 +962,79 @@ ], "initialIsOpen": false }, + { + "parentPluginId": "taskManager", + "id": "def-server.DecoratedError", + "type": "Interface", + "tags": [], + "label": "DecoratedError", + "description": [], + "signature": [ + { + "pluginId": "taskManager", + "scope": "server", + "docId": "kibTaskManagerPluginApi", + "section": "def-server.DecoratedError", + "text": "DecoratedError" + }, + " extends Error" + ], + "path": "x-pack/plugins/task_manager/server/task_running/errors.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "taskManager", + "id": "def-server.DecoratedError.code", + "type": "string", + "tags": [], + "label": "[code]", + "description": [], + "signature": [ + "string | undefined" + ], + "path": "x-pack/plugins/task_manager/server/task_running/errors.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "taskManager", + "id": "def-server.DecoratedError.retry", + "type": "CompoundType", + "tags": [], + "label": "[retry]", + "description": [], + "signature": [ + "boolean | Date | undefined" + ], + "path": "x-pack/plugins/task_manager/server/task_running/errors.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "taskManager", + "id": "def-server.DecoratedError.source", + "type": "CompoundType", + "tags": [], + "label": "[source]", + "description": [], + "signature": [ + { + "pluginId": "taskManager", + "scope": "server", + "docId": "kibTaskManagerPluginApi", + "section": "def-server.TaskErrorSource", + "text": "TaskErrorSource" + }, + " | undefined" + ], + "path": "x-pack/plugins/task_manager/server/task_running/errors.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, { "parentPluginId": "taskManager", "id": "def-server.IntervalSchedule", @@ -1429,6 +1630,18 @@ } ], "enums": [ + { + "parentPluginId": "taskManager", + "id": "def-server.TaskErrorSource", + "type": "Enum", + "tags": [], + "label": "TaskErrorSource", + "description": [], + "path": "x-pack/plugins/task_manager/server/task_running/errors.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, { "parentPluginId": "taskManager", "id": "def-server.TaskStatus", diff --git a/api_docs/task_manager.mdx b/api_docs/task_manager.mdx index 2b1f2c718821d..602903ef9f6c3 100644 --- a/api_docs/task_manager.mdx +++ b/api_docs/task_manager.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/taskManager title: "taskManager" image: https://source.unsplash.com/400x175/?github description: API docs for the taskManager plugin -date: 2023-11-14 +date: 2023-11-16 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'taskManager'] --- import taskManagerObj from './task_manager.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/response-ops](https://github.com/orgs/elastic/teams/response-o | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 96 | 0 | 53 | 6 | +| 105 | 0 | 62 | 5 | ## Server diff --git a/api_docs/telemetry.mdx b/api_docs/telemetry.mdx index 5d36604c7e25f..55899b0789d28 100644 --- a/api_docs/telemetry.mdx +++ b/api_docs/telemetry.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/telemetry title: "telemetry" image: https://source.unsplash.com/400x175/?github description: API docs for the telemetry plugin -date: 2023-11-14 +date: 2023-11-16 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 14f206a2532cc..48423b3cd5113 100644 --- a/api_docs/telemetry_collection_manager.mdx +++ b/api_docs/telemetry_collection_manager.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/telemetryCollectionManager title: "telemetryCollectionManager" image: https://source.unsplash.com/400x175/?github description: API docs for the telemetryCollectionManager plugin -date: 2023-11-14 +date: 2023-11-16 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 7b0914726772f..91c2294ff1662 100644 --- a/api_docs/telemetry_collection_xpack.mdx +++ b/api_docs/telemetry_collection_xpack.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/telemetryCollectionXpack title: "telemetryCollectionXpack" image: https://source.unsplash.com/400x175/?github description: API docs for the telemetryCollectionXpack plugin -date: 2023-11-14 +date: 2023-11-16 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 1a5265f3aefe0..e4514a6fffd5e 100644 --- a/api_docs/telemetry_management_section.mdx +++ b/api_docs/telemetry_management_section.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/telemetryManagementSection title: "telemetryManagementSection" image: https://source.unsplash.com/400x175/?github description: API docs for the telemetryManagementSection plugin -date: 2023-11-14 +date: 2023-11-16 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 a7f04c5ca48ca..80ea2fd4442fd 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: 2023-11-14 +date: 2023-11-16 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 de31deba9c1af..4d11d75097c83 100644 --- a/api_docs/threat_intelligence.mdx +++ b/api_docs/threat_intelligence.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/threatIntelligence title: "threatIntelligence" image: https://source.unsplash.com/400x175/?github description: API docs for the threatIntelligence plugin -date: 2023-11-14 +date: 2023-11-16 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 f4c6ac6536d7e..7708843c1ad3d 100644 --- a/api_docs/timelines.mdx +++ b/api_docs/timelines.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/timelines title: "timelines" image: https://source.unsplash.com/400x175/?github description: API docs for the timelines plugin -date: 2023-11-14 +date: 2023-11-16 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 ad389481a1ccd..1f9ef01d6f136 100644 --- a/api_docs/transform.mdx +++ b/api_docs/transform.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/transform title: "transform" image: https://source.unsplash.com/400x175/?github description: API docs for the transform plugin -date: 2023-11-14 +date: 2023-11-16 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'transform'] --- import transformObj from './transform.devdocs.json'; diff --git a/api_docs/triggers_actions_ui.devdocs.json b/api_docs/triggers_actions_ui.devdocs.json index ca061e520518d..a21b1f53aa704 100644 --- a/api_docs/triggers_actions_ui.devdocs.json +++ b/api_docs/triggers_actions_ui.devdocs.json @@ -55,7 +55,7 @@ "label": "experimentalFeatures", "description": [], "signature": [ - "{ readonly rulesListDatagrid: boolean; readonly internalAlertsTable: boolean; readonly ruleTagFilter: boolean; readonly ruleStatusFilter: boolean; readonly rulesDetailLogs: boolean; readonly ruleUseExecutionStatus: boolean; readonly ruleKqlBar: boolean; }" + "{ readonly rulesListDatagrid: boolean; readonly internalAlertsTable: boolean; readonly ruleTagFilter: boolean; readonly ruleStatusFilter: boolean; readonly rulesDetailLogs: boolean; readonly ruleUseExecutionStatus: boolean; readonly ruleKqlBar: boolean; readonly isMustacheAutocompleteOn: boolean; readonly showMustacheAutocompleteSwitch: boolean; }" ], "path": "x-pack/plugins/triggers_actions_ui/public/plugin.ts", "deprecated": false, @@ -1570,7 +1570,7 @@ "label": "TextAreaWithMessageVariables", "description": [], "signature": [ - "({ messageVariables, paramsProperty, index, inputTargetValue, isDisabled, editAction, label, errors, helpText, }: React.PropsWithChildren) => JSX.Element" + "(props: Props) => React.ReactElement | null" ], "path": "x-pack/plugins/triggers_actions_ui/public/application/components/text_area_with_message_variables.tsx", "deprecated": false, @@ -1579,12 +1579,12 @@ { "parentPluginId": "triggersActionsUi", "id": "def-public.TextAreaWithMessageVariables.$1", - "type": "CompoundType", + "type": "Object", "tags": [], - "label": "{\n messageVariables,\n paramsProperty,\n index,\n inputTargetValue,\n isDisabled = false,\n editAction,\n label,\n errors,\n helpText,\n}", + "label": "props", "description": [], "signature": [ - "React.PropsWithChildren" + "Props" ], "path": "x-pack/plugins/triggers_actions_ui/public/application/components/text_area_with_message_variables.tsx", "deprecated": false, @@ -2275,6 +2275,20 @@ "deprecated": false, "trackAdoption": false }, + { + "parentPluginId": "triggersActionsUi", + "id": "def-public.ActionParamsProps.ruleTypeId", + "type": "string", + "tags": [], + "label": "ruleTypeId", + "description": [], + "signature": [ + "string | undefined" + ], + "path": "x-pack/plugins/triggers_actions_ui/public/types.ts", + "deprecated": false, + "trackAdoption": false + }, { "parentPluginId": "triggersActionsUi", "id": "def-public.ActionParamsProps.messageVariables", @@ -2979,7 +2993,7 @@ "description": [], "signature": [ "BasicFields", - " & { \"@timestamp\"?: string[] | undefined; \"event.action\"?: string[] | undefined; tags?: string[] | undefined; kibana?: string[] | undefined; \"kibana.alert.rule.rule_type_id\"?: string[] | undefined; \"kibana.alert.rule.consumer\"?: string[] | undefined; \"kibana.alert.rule.execution.uuid\"?: string[] | undefined; \"kibana.alert.instance.id\"?: string[] | undefined; \"kibana.alert.rule.category\"?: string[] | undefined; \"kibana.alert.rule.name\"?: string[] | undefined; \"kibana.alert.rule.producer\"?: string[] | undefined; \"kibana.alert.rule.uuid\"?: string[] | undefined; \"kibana.alert.status\"?: string[] | undefined; \"kibana.alert.uuid\"?: string[] | undefined; \"kibana.space_ids\"?: string[] | undefined; \"event.kind\"?: string[] | undefined; \"kibana.alert.action_group\"?: string[] | undefined; \"kibana.alert.case_ids\"?: string[] | undefined; \"kibana.alert.duration.us\"?: string[] | undefined; \"kibana.alert.end\"?: string[] | undefined; \"kibana.alert.flapping\"?: string[] | undefined; \"kibana.alert.maintenance_window_ids\"?: string[] | undefined; \"kibana.alert.reason\"?: string[] | undefined; \"kibana.alert.rule.parameters\"?: string[] | undefined; \"kibana.alert.rule.tags\"?: string[] | undefined; \"kibana.alert.start\"?: string[] | undefined; \"kibana.alert.time_range\"?: string[] | undefined; \"kibana.alert.workflow_status\"?: string[] | undefined; \"kibana.alert.workflow_tags\"?: string[] | undefined; \"kibana.version\"?: string[] | undefined; \"kibana.alert\"?: string[] | undefined; \"kibana.alert.rule\"?: string[] | undefined; \"kibana.alert.risk_score\"?: string[] | undefined; \"kibana.alert.rule.author\"?: string[] | undefined; \"kibana.alert.rule.created_at\"?: string[] | undefined; \"kibana.alert.rule.created_by\"?: string[] | undefined; \"kibana.alert.rule.description\"?: string[] | undefined; \"kibana.alert.rule.enabled\"?: string[] | undefined; \"kibana.alert.rule.from\"?: string[] | undefined; \"kibana.alert.rule.interval\"?: string[] | undefined; \"kibana.alert.rule.license\"?: string[] | undefined; \"kibana.alert.rule.note\"?: string[] | undefined; \"kibana.alert.rule.references\"?: string[] | undefined; \"kibana.alert.rule.rule_id\"?: string[] | undefined; \"kibana.alert.rule.rule_name_override\"?: string[] | undefined; \"kibana.alert.rule.to\"?: string[] | undefined; \"kibana.alert.rule.type\"?: string[] | undefined; \"kibana.alert.rule.updated_at\"?: string[] | undefined; \"kibana.alert.rule.updated_by\"?: string[] | undefined; \"kibana.alert.rule.version\"?: string[] | undefined; \"kibana.alert.severity\"?: string[] | undefined; \"kibana.alert.suppression.docs_count\"?: string[] | undefined; \"kibana.alert.suppression.end\"?: string[] | undefined; \"kibana.alert.suppression.terms\"?: string[] | undefined; \"kibana.alert.suppression.terms.field\"?: string[] | undefined; \"kibana.alert.suppression.start\"?: string[] | undefined; \"kibana.alert.suppression.terms.value\"?: string[] | undefined; \"kibana.alert.system_status\"?: string[] | undefined; \"kibana.alert.workflow_reason\"?: string[] | undefined; \"kibana.alert.workflow_user\"?: string[] | undefined; \"ecs.version\"?: string[] | undefined; \"kibana.alert.evaluation.threshold\"?: string[] | undefined; \"kibana.alert.evaluation.value\"?: string[] | undefined; \"kibana.alert.context\"?: string[] | undefined; \"kibana.alert.evaluation.values\"?: string[] | undefined; \"kibana.alert.group\"?: string[] | undefined; \"kibana.alert.group.field\"?: string[] | undefined; \"kibana.alert.group.value\"?: string[] | undefined; \"event.module\"?: string[] | undefined; \"kibana.alert.building_block_type\"?: string[] | undefined; \"kibana.alert.rule.exceptions_list\"?: string[] | undefined; \"kibana.alert.rule.namespace\"?: string[] | undefined; \"kibana.alert.rule.threat.framework\"?: string[] | undefined; \"kibana.alert.rule.threat.tactic.id\"?: string[] | undefined; \"kibana.alert.rule.threat.tactic.name\"?: string[] | undefined; \"kibana.alert.rule.threat.tactic.reference\"?: string[] | undefined; \"kibana.alert.rule.threat.technique.id\"?: string[] | undefined; \"kibana.alert.rule.threat.technique.name\"?: string[] | undefined; \"kibana.alert.rule.threat.technique.reference\"?: string[] | undefined; \"kibana.alert.rule.threat.technique.subtechnique.id\"?: string[] | undefined; \"kibana.alert.rule.threat.technique.subtechnique.name\"?: string[] | undefined; \"kibana.alert.rule.threat.technique.subtechnique.reference\"?: string[] | undefined; } & { [x: string]: unknown[]; }" + " & { \"@timestamp\"?: string[] | undefined; \"event.action\"?: string[] | undefined; tags?: string[] | undefined; kibana?: string[] | undefined; \"kibana.alert.rule.rule_type_id\"?: string[] | undefined; \"kibana.alert.rule.consumer\"?: string[] | undefined; \"kibana.alert.rule.execution.uuid\"?: string[] | undefined; \"kibana.alert.instance.id\"?: string[] | undefined; \"kibana.alert.rule.category\"?: string[] | undefined; \"kibana.alert.rule.name\"?: string[] | undefined; \"kibana.alert.rule.producer\"?: string[] | undefined; \"kibana.alert.rule.uuid\"?: string[] | undefined; \"kibana.alert.status\"?: string[] | undefined; \"kibana.alert.uuid\"?: string[] | undefined; \"kibana.space_ids\"?: string[] | undefined; \"event.kind\"?: string[] | undefined; \"kibana.alert.action_group\"?: string[] | undefined; \"kibana.alert.case_ids\"?: string[] | undefined; \"kibana.alert.duration.us\"?: string[] | undefined; \"kibana.alert.end\"?: string[] | undefined; \"kibana.alert.flapping\"?: string[] | undefined; \"kibana.alert.maintenance_window_ids\"?: string[] | undefined; \"kibana.alert.reason\"?: string[] | undefined; \"kibana.alert.rule.parameters\"?: string[] | undefined; \"kibana.alert.rule.tags\"?: string[] | undefined; \"kibana.alert.start\"?: string[] | undefined; \"kibana.alert.time_range\"?: string[] | undefined; \"kibana.alert.workflow_status\"?: string[] | undefined; \"kibana.alert.workflow_tags\"?: string[] | undefined; \"kibana.version\"?: string[] | undefined; \"kibana.alert.context\"?: string[] | undefined; \"kibana.alert.evaluation.threshold\"?: string[] | undefined; \"kibana.alert.evaluation.value\"?: string[] | undefined; \"kibana.alert.evaluation.values\"?: string[] | undefined; \"kibana.alert.group\"?: string[] | undefined; \"ecs.version\"?: string[] | undefined; \"kibana.alert.risk_score\"?: string[] | undefined; \"kibana.alert.rule.author\"?: string[] | undefined; \"kibana.alert.rule.created_at\"?: string[] | undefined; \"kibana.alert.rule.created_by\"?: string[] | undefined; \"kibana.alert.rule.description\"?: string[] | undefined; \"kibana.alert.rule.enabled\"?: string[] | undefined; \"kibana.alert.rule.from\"?: string[] | undefined; \"kibana.alert.rule.interval\"?: string[] | undefined; \"kibana.alert.rule.license\"?: string[] | undefined; \"kibana.alert.rule.note\"?: string[] | undefined; \"kibana.alert.rule.references\"?: string[] | undefined; \"kibana.alert.rule.rule_id\"?: string[] | undefined; \"kibana.alert.rule.rule_name_override\"?: string[] | undefined; \"kibana.alert.rule.to\"?: string[] | undefined; \"kibana.alert.rule.type\"?: string[] | undefined; \"kibana.alert.rule.updated_at\"?: string[] | undefined; \"kibana.alert.rule.updated_by\"?: string[] | undefined; \"kibana.alert.rule.version\"?: string[] | undefined; \"kibana.alert.severity\"?: string[] | undefined; \"kibana.alert.suppression.docs_count\"?: string[] | undefined; \"kibana.alert.suppression.end\"?: string[] | undefined; \"kibana.alert.suppression.start\"?: string[] | undefined; \"kibana.alert.suppression.terms.field\"?: string[] | undefined; \"kibana.alert.suppression.terms.value\"?: string[] | undefined; \"kibana.alert.system_status\"?: string[] | undefined; \"kibana.alert.workflow_reason\"?: string[] | undefined; \"kibana.alert.workflow_user\"?: string[] | undefined; \"event.module\"?: string[] | undefined; \"kibana.alert.rule.threat.framework\"?: string[] | undefined; \"kibana.alert.rule.threat.tactic.id\"?: string[] | undefined; \"kibana.alert.rule.threat.tactic.name\"?: string[] | undefined; \"kibana.alert.rule.threat.tactic.reference\"?: string[] | undefined; \"kibana.alert.rule.threat.technique.id\"?: string[] | undefined; \"kibana.alert.rule.threat.technique.name\"?: string[] | undefined; \"kibana.alert.rule.threat.technique.reference\"?: string[] | undefined; \"kibana.alert.rule.threat.technique.subtechnique.id\"?: string[] | undefined; \"kibana.alert.rule.threat.technique.subtechnique.name\"?: string[] | undefined; \"kibana.alert.rule.threat.technique.subtechnique.reference\"?: string[] | undefined; \"kibana.alert.building_block_type\"?: string[] | undefined; \"kibana.alert\"?: string[] | undefined; \"kibana.alert.rule\"?: string[] | undefined; \"kibana.alert.suppression.terms\"?: string[] | undefined; \"kibana.alert.group.field\"?: string[] | undefined; \"kibana.alert.group.value\"?: string[] | undefined; \"kibana.alert.rule.exceptions_list\"?: string[] | undefined; \"kibana.alert.rule.namespace\"?: string[] | undefined; } & { [x: string]: unknown[]; }" ], "path": "x-pack/plugins/triggers_actions_ui/public/types.ts", "deprecated": false, @@ -4075,6 +4089,20 @@ "path": "x-pack/plugins/alerting/common/rule.ts", "deprecated": false, "trackAdoption": false + }, + { + "parentPluginId": "triggersActionsUi", + "id": "def-public.RuleAction.useAlertDataForTemplate", + "type": "CompoundType", + "tags": [], + "label": "useAlertDataForTemplate", + "description": [], + "signature": [ + "boolean | undefined" + ], + "path": "x-pack/plugins/alerting/common/rule.ts", + "deprecated": false, + "trackAdoption": false } ], "initialIsOpen": false @@ -6140,7 +6168,7 @@ "EuiDataGridToolBarVisibilityOptions", " | undefined; shouldHighlightRow?: ((alert: ", "EcsFieldsResponse", - ") => boolean) | undefined; featureIds?: ", + ") => boolean) | undefined; dynamicRowHeight?: boolean | undefined; featureIds?: ", { "pluginId": "@kbn/rule-data-utils", "scope": "common", @@ -9226,10 +9254,10 @@ ], "label": "parseExperimentalConfigValue", "description": [ - "\nParses the string value used in `xpack.trigger_actions_ui.enableExperimental` kibana configuration,\nwhich should be a string of values delimited by a comma (`,`)\n" + "\nParses the string value used in `xpack.trigger_actions_ui.enableExperimental` kibana configuration,\nwhich should be a string of values delimited by a comma (`,`):\nxpack.trigger_actions_ui.enableExperimental: ['ruleStatusFilter', 'ruleTagFilter']\n" ], "signature": [ - "(configValue: string[]) => Readonly<{ rulesListDatagrid: boolean; internalAlertsTable: boolean; ruleTagFilter: boolean; ruleStatusFilter: boolean; rulesDetailLogs: boolean; ruleUseExecutionStatus: boolean; ruleKqlBar: boolean; }>" + "(configValue: string[]) => Readonly<{ rulesListDatagrid: boolean; internalAlertsTable: boolean; ruleTagFilter: boolean; ruleStatusFilter: boolean; rulesDetailLogs: boolean; ruleUseExecutionStatus: boolean; ruleKqlBar: boolean; isMustacheAutocompleteOn: boolean; showMustacheAutocompleteSwitch: boolean; }>" ], "path": "x-pack/plugins/triggers_actions_ui/common/experimental_features.ts", "deprecated": false, @@ -9829,7 +9857,7 @@ "label": "ExperimentalFeatures", "description": [], "signature": [ - "{ readonly rulesListDatagrid: boolean; readonly internalAlertsTable: boolean; readonly ruleTagFilter: boolean; readonly ruleStatusFilter: boolean; readonly rulesDetailLogs: boolean; readonly ruleUseExecutionStatus: boolean; readonly ruleKqlBar: boolean; }" + "{ readonly rulesListDatagrid: boolean; readonly internalAlertsTable: boolean; readonly ruleTagFilter: boolean; readonly ruleStatusFilter: boolean; readonly rulesDetailLogs: boolean; readonly ruleUseExecutionStatus: boolean; readonly ruleKqlBar: boolean; readonly isMustacheAutocompleteOn: boolean; readonly showMustacheAutocompleteSwitch: boolean; }" ], "path": "x-pack/plugins/triggers_actions_ui/common/experimental_features.ts", "deprecated": false, @@ -9893,7 +9921,7 @@ "\nA list of allowed values that can be used in `xpack.trigger_actions_ui.enableExperimental`.\nThis object is then used to validate and parse the value entered." ], "signature": [ - "{ readonly rulesListDatagrid: boolean; readonly internalAlertsTable: boolean; readonly ruleTagFilter: boolean; readonly ruleStatusFilter: boolean; readonly rulesDetailLogs: boolean; readonly ruleUseExecutionStatus: boolean; readonly ruleKqlBar: boolean; }" + "{ readonly rulesListDatagrid: boolean; readonly internalAlertsTable: boolean; readonly ruleTagFilter: boolean; readonly ruleStatusFilter: boolean; readonly rulesDetailLogs: boolean; readonly ruleUseExecutionStatus: boolean; readonly ruleKqlBar: boolean; readonly isMustacheAutocompleteOn: boolean; readonly showMustacheAutocompleteSwitch: boolean; }" ], "path": "x-pack/plugins/triggers_actions_ui/common/experimental_features.ts", "deprecated": false, diff --git a/api_docs/triggers_actions_ui.mdx b/api_docs/triggers_actions_ui.mdx index ee7c087e39216..8076002044f80 100644 --- a/api_docs/triggers_actions_ui.mdx +++ b/api_docs/triggers_actions_ui.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/triggersActionsUi title: "triggersActionsUi" image: https://source.unsplash.com/400x175/?github description: API docs for the triggersActionsUi plugin -date: 2023-11-14 +date: 2023-11-16 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'triggersActionsUi'] --- import triggersActionsUiObj from './triggers_actions_ui.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/response-ops](https://github.com/orgs/elastic/teams/response-o | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 581 | 1 | 555 | 55 | +| 583 | 1 | 557 | 55 | ## Client diff --git a/api_docs/ui_actions.devdocs.json b/api_docs/ui_actions.devdocs.json index 8aa60c3c65f77..fc3e6efa4a21a 100644 --- a/api_docs/ui_actions.devdocs.json +++ b/api_docs/ui_actions.devdocs.json @@ -2218,7 +2218,7 @@ "section": "def-common.FieldAttrs", "text": "FieldAttrs" }, - " | undefined; allowNoIndex?: boolean | undefined; namespaces?: string[] | undefined; name?: string | undefined; }" + " | undefined; allowNoIndex?: boolean | undefined; namespaces?: string[] | undefined; name?: string | undefined; allowHidden?: boolean | undefined; }" ], "path": "src/plugins/ui_actions/public/types.ts", "deprecated": false, diff --git a/api_docs/ui_actions.mdx b/api_docs/ui_actions.mdx index 2aa732bd3a3ed..1c8f3f5e83445 100644 --- a/api_docs/ui_actions.mdx +++ b/api_docs/ui_actions.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/uiActions title: "uiActions" image: https://source.unsplash.com/400x175/?github description: API docs for the uiActions plugin -date: 2023-11-14 +date: 2023-11-16 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 26eec2f9e302d..bc7c3d55f0c60 100644 --- a/api_docs/ui_actions_enhanced.mdx +++ b/api_docs/ui_actions_enhanced.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/uiActionsEnhanced title: "uiActionsEnhanced" image: https://source.unsplash.com/400x175/?github description: API docs for the uiActionsEnhanced plugin -date: 2023-11-14 +date: 2023-11-16 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 72f84ad374392..dff22e1edd0b6 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: 2023-11-14 +date: 2023-11-16 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 dfdf6a256c6d8..1b8cde0683132 100644 --- a/api_docs/unified_histogram.mdx +++ b/api_docs/unified_histogram.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/unifiedHistogram title: "unifiedHistogram" image: https://source.unsplash.com/400x175/?github description: API docs for the unifiedHistogram plugin -date: 2023-11-14 +date: 2023-11-16 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 0c535bc25d008..dd540663bb609 100644 --- a/api_docs/unified_search.mdx +++ b/api_docs/unified_search.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/unifiedSearch title: "unifiedSearch" image: https://source.unsplash.com/400x175/?github description: API docs for the unifiedSearch plugin -date: 2023-11-14 +date: 2023-11-16 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 f1d7288b74c6a..996c7f5528dcc 100644 --- a/api_docs/unified_search_autocomplete.mdx +++ b/api_docs/unified_search_autocomplete.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/unifiedSearch-autocomplete title: "unifiedSearch.autocomplete" image: https://source.unsplash.com/400x175/?github description: API docs for the unifiedSearch.autocomplete plugin -date: 2023-11-14 +date: 2023-11-16 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 11ea0e3c57564..814bcd995e63a 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: 2023-11-14 +date: 2023-11-16 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 7b6b575a2d182..9f93b59207c10 100644 --- a/api_docs/url_forwarding.mdx +++ b/api_docs/url_forwarding.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/urlForwarding title: "urlForwarding" image: https://source.unsplash.com/400x175/?github description: API docs for the urlForwarding plugin -date: 2023-11-14 +date: 2023-11-16 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 6aff7680c6c93..fb864ad037986 100644 --- a/api_docs/usage_collection.mdx +++ b/api_docs/usage_collection.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/usageCollection title: "usageCollection" image: https://source.unsplash.com/400x175/?github description: API docs for the usageCollection plugin -date: 2023-11-14 +date: 2023-11-16 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 80589d2c69f52..8098cf149e57e 100644 --- a/api_docs/ux.mdx +++ b/api_docs/ux.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/ux title: "ux" image: https://source.unsplash.com/400x175/?github description: API docs for the ux plugin -date: 2023-11-14 +date: 2023-11-16 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 c4b337379170c..40877abcb6348 100644 --- a/api_docs/vis_default_editor.mdx +++ b/api_docs/vis_default_editor.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visDefaultEditor title: "visDefaultEditor" image: https://source.unsplash.com/400x175/?github description: API docs for the visDefaultEditor plugin -date: 2023-11-14 +date: 2023-11-16 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 c30aca643ad13..0d4725984ca1e 100644 --- a/api_docs/vis_type_gauge.mdx +++ b/api_docs/vis_type_gauge.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypeGauge title: "visTypeGauge" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypeGauge plugin -date: 2023-11-14 +date: 2023-11-16 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 18c72d541f211..7857b49c7ecdc 100644 --- a/api_docs/vis_type_heatmap.mdx +++ b/api_docs/vis_type_heatmap.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypeHeatmap title: "visTypeHeatmap" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypeHeatmap plugin -date: 2023-11-14 +date: 2023-11-16 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 6e2654ee450e3..c1307ba118b0b 100644 --- a/api_docs/vis_type_pie.mdx +++ b/api_docs/vis_type_pie.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypePie title: "visTypePie" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypePie plugin -date: 2023-11-14 +date: 2023-11-16 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 7a53a82e6c28c..37333abc730d5 100644 --- a/api_docs/vis_type_table.mdx +++ b/api_docs/vis_type_table.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypeTable title: "visTypeTable" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypeTable plugin -date: 2023-11-14 +date: 2023-11-16 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 d1171f69044d5..cb39b15983e16 100644 --- a/api_docs/vis_type_timelion.mdx +++ b/api_docs/vis_type_timelion.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypeTimelion title: "visTypeTimelion" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypeTimelion plugin -date: 2023-11-14 +date: 2023-11-16 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 c4ae6ef430b9b..882aaf0a79f71 100644 --- a/api_docs/vis_type_timeseries.mdx +++ b/api_docs/vis_type_timeseries.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypeTimeseries title: "visTypeTimeseries" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypeTimeseries plugin -date: 2023-11-14 +date: 2023-11-16 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 dbbfd12ca2464..d1fa982b691c8 100644 --- a/api_docs/vis_type_vega.mdx +++ b/api_docs/vis_type_vega.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypeVega title: "visTypeVega" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypeVega plugin -date: 2023-11-14 +date: 2023-11-16 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 b58679760723b..7084cbc94b13e 100644 --- a/api_docs/vis_type_vislib.mdx +++ b/api_docs/vis_type_vislib.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypeVislib title: "visTypeVislib" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypeVislib plugin -date: 2023-11-14 +date: 2023-11-16 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 743f41cf5578b..44036f2755796 100644 --- a/api_docs/vis_type_xy.mdx +++ b/api_docs/vis_type_xy.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypeXy title: "visTypeXy" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypeXy plugin -date: 2023-11-14 +date: 2023-11-16 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 1b4eb431303b8..ce10e1dd34ed8 100644 --- a/api_docs/visualizations.mdx +++ b/api_docs/visualizations.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visualizations title: "visualizations" image: https://source.unsplash.com/400x175/?github description: API docs for the visualizations plugin -date: 2023-11-14 +date: 2023-11-16 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visualizations'] --- import visualizationsObj from './visualizations.devdocs.json'; diff --git a/config/serverless.es.yml b/config/serverless.es.yml index 8a81fbe5f48ae..e724eb5207ede 100644 --- a/config/serverless.es.yml +++ b/config/serverless.es.yml @@ -9,10 +9,7 @@ xpack.observabilityLogExplorer.enabled: false xpack.observability.enabled: false xpack.securitySolution.enabled: false xpack.serverless.observability.enabled: false -xpack.uptime.enabled: false -xpack.legacy_uptime.enabled: false enterpriseSearch.enabled: false -monitoring.ui.enabled: false xpack.fleet.enabled: false ## Cloud settings diff --git a/config/serverless.oblt.yml b/config/serverless.oblt.yml index 68f340fb64c05..86b3aabadbe5e 100644 --- a/config/serverless.oblt.yml +++ b/config/serverless.oblt.yml @@ -5,8 +5,6 @@ enterpriseSearch.enabled: false xpack.cloudSecurityPosture.enabled: false xpack.infra.enabled: true xpack.securitySolution.enabled: false -xpack.uptime.enabled: false -xpack.legacy_uptime.enabled: false ## Cloud settings xpack.cloud.serverless.project_type: observability diff --git a/config/serverless.security.yml b/config/serverless.security.yml index 7f749afc7626d..f47d3b02a1bf0 100644 --- a/config/serverless.security.yml +++ b/config/serverless.security.yml @@ -6,8 +6,6 @@ xpack.apm.enabled: false xpack.infra.enabled: false xpack.observabilityLogExplorer.enabled: false xpack.observability.enabled: false -xpack.uptime.enabled: false -xpack.legacy_uptime.enabled: false ## Cloud settings xpack.cloud.serverless.project_type: security diff --git a/config/serverless.yml b/config/serverless.yml index a6aba80736f2d..30aa06ab8f05b 100644 --- a/config/serverless.yml +++ b/config/serverless.yml @@ -127,7 +127,7 @@ xpack.alerting.rules.run.actions.max: 3000 xpack.alerting.rules.run.timeout: 1m xpack.alerting.rules.run.ruleTypeOverrides: - id: siem.indicatorRule - timeout: 1m + timeout: 10m xpack.alerting.rules.minimumScheduleInterval.enforce: true xpack.alerting.rules.maxScheduledPerMinute: 400 xpack.actions.run.maxAttempts: 10 @@ -150,6 +150,14 @@ xpack.reporting.queue.pollInterval: 3m xpack.reporting.roles.enabled: false xpack.reporting.statefulSettings.enabled: false - # Disabled Observability plugins xpack.ux.enabled: false +xpack.monitoring.enabled: false +xpack.uptime.enabled: false +xpack.legacy_uptime.enabled: false +monitoring.ui.enabled: false + +## Enable uiSettings validations +xpack.securitySolution.enableUiSettingsValidations: true +data.enableUiSettingsValidations: true +discover.enableUiSettingsValidations: true diff --git a/dev_docs/key_concepts/anatomy_of_a_plugin.mdx b/dev_docs/key_concepts/anatomy_of_a_plugin.mdx index c71897fc34fcb..6b90fa0b0c938 100644 --- a/dev_docs/key_concepts/anatomy_of_a_plugin.mdx +++ b/dev_docs/key_concepts/anatomy_of_a_plugin.mdx @@ -122,7 +122,7 @@ If you are developing in TypeScript (which we recommend), you will need to add a core capabilities as an argument. It should return an instance of its plugin class for Kibana to load. ```ts -import type { PluginInitializerContext } from '@kbn/core/server'; +import type { PluginInitializerContext } from '@kbn/core/public'; import { DemoPlugin } from './plugin'; export function plugin(initializerContext: PluginInitializerContext) { @@ -177,7 +177,16 @@ export class DemoPlugin implements Plugin { ### server/index.ts -`server/index.ts` is the entry-point into the server-side code of this plugin. It is identical in almost every way to the client-side entry-point: +`server/index.ts` is the entry-point into the server-side code of this plugin. + +```ts +import type { PluginInitializerContext } from '@kbn/core/server'; + +export async function plugin(initializerContext: PluginInitializerContext) { + const { DemoPlugin } = await import('./plugin'); + return new DemoPlugin(initializerContext); +} +``` ### server/plugin.ts diff --git a/docs/CHANGELOG.asciidoc b/docs/CHANGELOG.asciidoc index 73bb3a87fbadb..1b7d6e6b88321 100644 --- a/docs/CHANGELOG.asciidoc +++ b/docs/CHANGELOG.asciidoc @@ -58,14 +58,35 @@ Review important information about the {kib} 8.x releases. [[release-notes-8.11.1]] == {kib} 8.11.1 -The 8.11.1 release includes the following bug fixes. +For information about the {kib} 8.11.1 release, review the following information. + +[float] +[[security-update-v8.11.1]] +=== Security updates + +* An issue was discovered by Elastic whereby sensitive information is recorded +in {kib} logs in the event of an error. The error message recorded in the log +may contain account credentials for the `kibana_system` user, API Keys, and +credentials of {kib} end users. ++ +-- +The issue impacts {kib} {kib} versions on or after 8.0.0 and before 8.11.1. The +issue is resolved in {kib} 8.11.1. + +**Nov 15, 2023 Update:** After additional investigation, it has been determined +that {kib} 7.x versions are not affected by this issue. We previously reported +this issue impacted {kib} versions before 7.17.15. + +For more information, see our related +https://discuss.elastic.co/t/8-11-1-7-17-15-security-update-esa-2023-25/347149[security +announcement]. +-- [float] [[fixes-v8.11.1]] === Bug Fixes Fleet:: -* Fixes inability to upgrade agents from version 8.10.4 to version 8.11 ({kibana-pull}170974[#170974]). * Append space ID to security solution tag ({kibana-pull}170789[#170789]). * Modify bulk unenroll to include inactive agents ({kibana-pull}170249[#170249]). Lens & Visualizations:: @@ -799,10 +820,10 @@ For information about the {kib} 8.9.0 release, review the following information. [%collapsible] ==== *Details* + -Changes to Lens visualizations do not appear in the saved object. +Changes to Lens visualizations do not appear in the saved object. *Impact* + -When you remove fields from Lens visualizations, then save your changes, the removed fields continue to appear in the Lens visualization saved objects. +When you remove fields from Lens visualizations, then save your changes, the removed fields continue to appear in the Lens visualization saved objects. For example, when you remove runtime fields from a Lens visualization and {kib}, then inspect the Lens visualization saved object, the runtime fields continue to appear and an error message appears. *Workaround* + diff --git a/docs/developer/architecture/core/configuration-service.asciidoc b/docs/developer/architecture/core/configuration-service.asciidoc index ed03be73296cb..86c4d5050b0b9 100644 --- a/docs/developer/architecture/core/configuration-service.asciidoc +++ b/docs/developer/architecture/core/configuration-service.asciidoc @@ -35,7 +35,7 @@ export type MyPluginConfigType = TypeOf; * Read config value exposed via `PluginInitializerContext`: -*my_plugin/server/index.ts* +*my_plugin/server/plugin.ts* [source,typescript] ---- import type { PluginInitializerContext } from '@kbn/core/server'; diff --git a/docs/developer/architecture/kibana-platform-plugin-api.asciidoc b/docs/developer/architecture/kibana-platform-plugin-api.asciidoc index 85fc05d0f9fd8..4c23aead9d566 100644 --- a/docs/developer/architecture/kibana-platform-plugin-api.asciidoc +++ b/docs/developer/architecture/kibana-platform-plugin-api.asciidoc @@ -100,9 +100,9 @@ entry-point: [source,typescript] ---- import type { PluginInitializerContext } from '@kbn/core/server'; -import { MyPlugin } from './plugin'; -export function plugin(initializerContext: PluginInitializerContext) { +export async function plugin(initializerContext: PluginInitializerContext) { + const { MyPlugin } = await import('./plugin'); return new MyPlugin(initializerContext); } ---- diff --git a/docs/osquery/exported-fields-reference.asciidoc b/docs/osquery/exported-fields-reference.asciidoc index fc16ec3e0d9d0..b3127f2ad48cf 100644 --- a/docs/osquery/exported-fields-reference.asciidoc +++ b/docs/osquery/exported-fields-reference.asciidoc @@ -96,6 +96,10 @@ For more information about osquery tables, see the https://osquery.io/schema[osq * _wifi_networks.added_at_ - Time this network was added as a unix_time +*additional_properties* - keyword, text.text + +* _windows_search.additional_properties_ - Comma separated list of columns to include in properties JSON + *address* - keyword, text.text * _arp_cache.address_ - IPv4 address target @@ -141,6 +145,10 @@ For more information about osquery tables, see the https://osquery.io/schema[osq * _alf.allow_signed_enabled_ - 1 If allow signed mode is enabled else 0 +*ambient_brightness_enabled* - keyword, text.text + +* _connected_displays.ambient_brightness_enabled_ - The ambient brightness setting associated with the display. This will be 1 if enabled and is 0 if disabled or not supported. + *ami_id* - keyword, text.text * _ec2_instance_metadata.ami_id_ - AMI ID used to launch this EC2 instance @@ -583,6 +591,7 @@ For more information about osquery tables, see the https://osquery.io/schema[osq *bundle_version* - keyword, text.text * _apps.bundle_version_ - Info properties CFBundleVersion label +* _safari_extensions.bundle_version_ - The version of the build that identifies an iteration of the bundle *busy_state* - keyword, number.long @@ -777,11 +786,16 @@ For more information about osquery tables, see the https://osquery.io/schema[osq * _ntdomains.client_site_name_ - The name of the site where the domain controller is configured. +*cloud_id* - keyword, text.text + +* _ycloud_instance_metadata.cloud_id_ - Cloud identifier for the VM + *cmdline* - keyword, text.text * _bpf_process_events.cmdline_ - Command line arguments * _docker_container_processes.cmdline_ - Complete argv * _es_process_events.cmdline_ - Command line arguments (argv) +* _process_etw_events.cmdline_ - Command Line * _process_events.cmdline_ - Command line arguments (argv) * _processes.cmdline_ - Complete argv @@ -973,6 +987,10 @@ For more information about osquery tables, see the https://osquery.io/schema[osq * _interface_details.connection_status_ - State of the network adapter connection to the network. +*connection_type* - keyword, text.text + +* _connected_displays.connection_type_ - The connection type associated with the display. + *consistency_scan_date* - keyword, number.long * _time_machine_destinations.consistency_scan_date_ - Consistency scan date @@ -1024,6 +1042,7 @@ For more information about osquery tables, see the https://osquery.io/schema[osq *copyright* - keyword, text.text * _apps.copyright_ - Info properties NSHumanReadableCopyright label +* _safari_extensions.copyright_ - A human-readable copyright notice for the bundle *core* - keyword, number.long @@ -1088,6 +1107,10 @@ For more information about osquery tables, see the https://osquery.io/schema[osq * _docker_info.cpu_shares_ - 1 if CPU share weighting support is enabled. 0 otherwise +*cpu_sockets* - keyword, number.long + +* _system_info.cpu_sockets_ - Number of processor sockets in the system + *cpu_spec_ctrl_supported* - keyword, number.long * _kva_speculative_info.cpu_spec_ctrl_supported_ - SPEC_CTRL MSR supported by CPU Microcode. @@ -1236,10 +1259,19 @@ For more information about osquery tables, see the https://osquery.io/schema[osq * _platform_info.date_ - Self-reported platform code update date * _windows_update_history.date_ - Date and the time an update was applied +*date_created* - keyword, number.long + +* _windows_search.date_created_ - The unix timestamp of when the item was created. + +*date_modified* - keyword, number.long + +* _windows_search.date_modified_ - The unix timestamp of when the item was last modified + *datetime* - keyword, text.text * _crashes.datetime_ - Date/Time at which the crash occurred * _powershell_events.datetime_ - System time at which the Powershell script event occurred +* _process_etw_events.datetime_ - Event timestamp in DATETIME format * _syslog_events.datetime_ - Time known to syslog * _time.datetime_ - Current date and time (ISO format) in UTC * _windows_crashes.datetime_ - Timestamp (log format) of the crash @@ -1306,6 +1338,7 @@ For more information about osquery tables, see the https://osquery.io/schema[osq * _drivers.description_ - Driver description * _firefox_addons.description_ - Addon-supplied description string * _interface_details.description_ - Short description of the object a one-line string. +* _kernel_keys.description_ - The key description. * _keychain_acls.description_ - The description included with the ACL entry * _keychain_items.description_ - Optional item description * _logical_drives.description_ - The canonical description of the drive, e.g. 'Logical Fixed Disk', 'CD-ROM Disk'. @@ -1481,11 +1514,19 @@ For more information about osquery tables, see the https://osquery.io/schema[osq * _docker_container_stats.disk_write_ - Total disk write bytes +*display_id* - keyword, text.text + +* _connected_displays.display_id_ - The display ID. + *display_name* - keyword, text.text * _apps.display_name_ - Info properties CFBundleDisplayName label * _services.display_name_ - Service Display name +*display_type* - keyword, text.text + +* _connected_displays.display_type_ - The type of display. + *dns_domain* - keyword, text.text * _interface_details.dns_domain_ - Organization name followed by a period and an extension that indicates the type of organization, such as 'microsoft.com'. @@ -1607,6 +1648,7 @@ For more information about osquery tables, see the https://osquery.io/schema[osq * _file_events.eid_ - Event ID * _hardware_events.eid_ - Event ID * _ntfs_journal_events.eid_ - Event ID +* _process_etw_events.eid_ - Event ID * _process_events.eid_ - Event ID * _process_file_events.eid_ - Event ID * _selinux_events.eid_ - Event ID @@ -1837,6 +1879,7 @@ For more information about osquery tables, see the https://osquery.io/schema[osq * _bpf_process_events.exit_code_ - Exit code of the system call * _bpf_socket_events.exit_code_ - Exit code of the system call * _es_process_events.exit_code_ - Exit code of a process in case of an exit event +* _process_etw_events.exit_code_ - Exit Code - Present only on ProcessStop events *expand* - keyword, number.long @@ -1854,6 +1897,10 @@ For more information about osquery tables, see the https://osquery.io/schema[osq * _curl_certificate.extended_key_usage_ - Extended usage of key in certificate +*extension_type* - keyword, text.text + +* _safari_extensions.extension_type_ - Extension Type: WebOrAppExtension or LegacyExtension + *extensions* - keyword, text.text * _osquery_info.extensions_ - osquery extensions status @@ -1865,6 +1912,7 @@ For more information about osquery tables, see the https://osquery.io/schema[osq *extra* - keyword, text.text * _asl.extra_ - Extra columns, in JSON format. Queries against this column are performed entirely in SQLite, so do not benefit from efficient querying via asl.h. +* _os_version.extra_ - Optional extra release specification * _platform_info.extra_ - Platform-specific additional information *facility* - keyword, text.text @@ -2018,8 +2066,10 @@ For more information about osquery tables, see the https://osquery.io/schema[osq * _device_partitions.flags_ - * _dns_cache.flags_ - DNS record flags * _interface_details.flags_ - Flags (netdevice) for the device +* _kernel_keys.flags_ - A set of flags describing the state of the key. * _mounts.flags_ - Mounted device flags * _pipes.flags_ - The flags indicating whether this pipe connection is a server or client end, and if the pipe for sending messages or bytes +* _process_etw_events.flags_ - Process Flags * _routes.flags_ - Flags to describe route *folder_id* - keyword, text.text @@ -2107,6 +2157,7 @@ For more information about osquery tables, see the https://osquery.io/schema[osq * _file.gid_ - Owning group ID * _file_events.gid_ - Owning group ID * _groups.gid_ - Unsigned int64 group ID +* _kernel_keys.gid_ - The group ID of the key. * _package_bom.gid_ - Expected group of file or directory * _process_events.gid_ - Group ID at process start * _process_file_events.gid_ - The gid of the process performing the action @@ -2240,6 +2291,10 @@ For more information about osquery tables, see the https://osquery.io/schema[osq * _sudoers.header_ - Symbol for given rule +*header_pid* - keyword, number.long + +* _process_etw_events.header_pid_ - Process ID of the process reporting the event + *header_size* - keyword, number.long * _smbios_tables.header_size_ - Header size in bytes @@ -3081,6 +3136,10 @@ For more information about osquery tables, see the https://osquery.io/schema[osq * _magic.magic_db_files_ - Colon(:) separated list of files where the magic db file can be found. By default one of the following is used: /usr/share/file/magic/magic, /usr/share/misc/magic or /usr/share/misc/magic.mgc +*main* - keyword, number.long + +* _connected_displays.main_ - If the display is the main display. + *maintainer* - keyword, text.text * _apt_sources.maintainer_ - Repository maintainer @@ -3098,6 +3157,10 @@ For more information about osquery tables, see the https://osquery.io/schema[osq * _lxd_networks.managed_ - 1 if network created by LXD, 0 otherwise +*mandatory_label* - keyword, text.text + +* _process_etw_events.mandatory_label_ - Primary token mandatory label sid - Present only on ProcessStart events + *manifest_hash* - keyword, text.text * _chrome_extensions.manifest_hash_ - The SHA256 hash of the manifest.json file @@ -3114,6 +3177,14 @@ For more information about osquery tables, see the https://osquery.io/schema[osq * _battery.manufacture_date_ - The date the battery was manufactured UNIX Epoch +*manufactured_week* - keyword, number.long + +* _connected_displays.manufactured_week_ - The manufacture week of the display. This field is 0 if not supported + +*manufactured_year* - keyword, number.long + +* _connected_displays.manufactured_year_ - The manufacture year of the display. This field is 0 if not supported + *manufacturer* - keyword, text.text * _battery.manufacturer_ - The battery manufacturer's name @@ -3170,6 +3241,10 @@ For more information about osquery tables, see the https://osquery.io/schema[osq * _pipes.max_instances_ - The maximum number of instances creatable for this pipe +*max_results* - keyword, number.long + +* _windows_search.max_results_ - Maximum number of results returned by windows api, set to -1 for unlimited + *max_rows* - keyword, number.long * _unified_log.max_rows_ - the max number of rows returned (defaults to 100) @@ -3258,6 +3333,10 @@ For more information about osquery tables, see the https://osquery.io/schema[osq * _memory_info.memory_available_ - The amount of physical RAM, in bytes, available for starting new applications, without swapping +*memory_cached* - keyword, number.long + +* _docker_container_stats.memory_cached_ - Memory cached + *memory_device_handle* - keyword, text.text * _memory_device_mapped_addresses.memory_device_handle_ - Handle of the memory device structure associated with this structure @@ -3400,6 +3479,10 @@ For more information about osquery tables, see the https://osquery.io/schema[osq * _battery.minutes_until_empty_ - The number of minutes until the battery is fully depleted. This value is -1 if this time is still being calculated +*mirror* - keyword, number.long + +* _connected_displays.mirror_ - If the display is mirrored or not. This field is 1 if mirrored and 0 if not mirrored. + *mirrorlist* - keyword, text.text * _yum_sources.mirrorlist_ - Mirrorlist URL @@ -3515,6 +3598,7 @@ For more information about osquery tables, see the https://osquery.io/schema[osq * _browser_plugins.name_ - Plugin display name * _chocolatey_packages.name_ - Package display name * _chrome_extensions.name_ - Extension display name +* _connected_displays.name_ - The name of the display. * _cups_destinations.name_ - Name of the printer * _deb_packages.name_ - Package name * _disk_encryption.name_ - Disk name @@ -3580,6 +3664,7 @@ For more information about osquery tables, see the https://osquery.io/schema[osq * _temperature_sensors.name_ - Name of temperature source * _windows_firewall_rules.name_ - Friendly name of the rule * _windows_optional_features.name_ - Name of the feature +* _windows_search.name_ - The name of the item * _windows_security_products.name_ - Name of product * _wmi_bios_info.name_ - Name of the Bios setting * _wmi_cli_event_consumers.name_ - Unique name of a consumer. @@ -3702,6 +3787,14 @@ For more information about osquery tables, see the https://osquery.io/schema[osq * _cpu_info.number_of_cores_ - The number of cores of the CPU. +*number_of_efficiency_cores* - keyword, number.long + +* _cpu_info.number_of_efficiency_cores_ - The number of efficiency cores of the CPU. Only available on Apple Silicon + +*number_of_performance_cores* - keyword, number.long + +* _cpu_info.number_of_performance_cores_ - The number of performance cores of the CPU. Only available on Apple Silicon + *object_name* - keyword, text.text * _winbaseobj.object_name_ - Object Name @@ -3751,6 +3844,10 @@ For more information about osquery tables, see the https://osquery.io/schema[osq * _processes.on_disk_ - The process path exists yes=1, no=0, unknown=-1 +*online* - keyword, number.long + +* _connected_displays.online_ - The online status of the display. This field is 1 if the display is online and 0 if it is offline. + *online_cpus* - keyword, number.long * _docker_container_stats.online_cpus_ - Online CPUs @@ -3880,6 +3977,10 @@ For more information about osquery tables, see the https://osquery.io/schema[osq * _tpm_info.owned_ - TPM is owned +*owner* - keyword, text.text + +* _windows_search.owner_ - The owner of the item + *owner_gid* - keyword, number.long * _process_events.owner_gid_ - File owner group ID @@ -3948,6 +4049,10 @@ For more information about osquery tables, see the https://osquery.io/schema[osq * _process_events.parent_ - Process parent's PID, or -1 if cannot be determined. * _processes.parent_ - Process parent's PID +*parent_process_sequence_number* - keyword, number.long + +* _process_etw_events.parent_process_sequence_number_ - Parent Process Sequence Number - Present only on ProcessStart events + *parent_ref_number* - keyword, text.text * _ntfs_journal_events.parent_ref_number_ - The ordinal that associates a journal record with a filename's parent directory @@ -4071,6 +4176,7 @@ For more information about osquery tables, see the https://osquery.io/schema[osq * _package_receipts.path_ - Path of receipt plist * _plist.path_ - (required) read preferences from a plist * _prefetch.path_ - Prefetch file path. +* _process_etw_events.path_ - Path of executed binary * _process_events.path_ - Path of executed file * _process_file_events.path_ - The path associated with the event * _process_memory_map.path_ - Path to mapped file or mapped type @@ -4098,6 +4204,7 @@ For more information about osquery tables, see the https://osquery.io/schema[osq * _user_ssh_keys.path_ - Path to key file * _userassist.path_ - Application file path. * _windows_crashes.path_ - Path of the executable file for the crashed process +* _windows_search.path_ - The full path of the item. * _yara.path_ - The path scanned *pci_class* - keyword, text.text @@ -4172,6 +4279,7 @@ For more information about osquery tables, see the https://osquery.io/schema[osq *permissions* - keyword, text.text * _chrome_extensions.permissions_ - The permissions required by the extension +* _kernel_keys.permissions_ - The key permissions, expressed as four hexadecimalbytes containing, from left to right, thepossessor, user, group, and other permissions. * _process_memory_map.permissions_ - r=read, w=write, x=execute, p=private (cow) * _shared_memory.permissions_ - Memory segment permissions * _suid_bin.permissions_ - Binary permissions @@ -4227,6 +4335,7 @@ For more information about osquery tables, see the https://osquery.io/schema[osq * _osquery_info.pid_ - Process (or thread/handle) ID * _pipes.pid_ - Process ID of the process to which the pipe belongs * _process_envs.pid_ - Process (or thread) ID +* _process_etw_events.pid_ - Process ID * _process_events.pid_ - Process (or thread) ID * _process_file_events.pid_ - Process ID * _process_memory_map.pid_ - Process (or thread) ID @@ -4268,12 +4377,21 @@ For more information about osquery tables, see the https://osquery.io/schema[osq * _suid_bin.pid_with_namespace_ - Pids that contain a namespace * _user_ssh_keys.pid_with_namespace_ - Pids that contain a namespace * _users.pid_with_namespace_ - Pids that contain a namespace +* _yara.pid_with_namespace_ - Pids that contain a namespace * _yum_sources.pid_with_namespace_ - Pids that contain a namespace *pids* - keyword, number.long * _docker_container_stats.pids_ - Number of processes +*pixels* - keyword, text.text + +* _connected_displays.pixels_ - The number of pixels of the display. + +*pk_hash* - keyword, text.text + +* _keychain_items.pk_hash_ - Hash of associated public key (SHA1 of subjectPublicKey, see RFC 8520 4.2.1.2) + *placement_group_id* - keyword, text.text * _azure_instance_metadata.placement_group_id_ - Placement group for the VM scale set @@ -4359,6 +4477,7 @@ For more information about osquery tables, see the https://osquery.io/schema[osq *ppid* - keyword, number.long +* _process_etw_events.ppid_ - Parent Process ID * _process_file_events.ppid_ - Parent process ID *pre_cpu_kernelmode_usage* - keyword, number.long @@ -4381,6 +4500,10 @@ For more information about osquery tables, see the https://osquery.io/schema[osq * _docker_container_stats.pre_system_cpu_usage_ - Last read CPU system usage +*predicate* - keyword, text.text + +* _unified_log.predicate_ - predicate to search (see `log help predicates`), note that this is merged into the predicate created from the column constraints + *prefix* - keyword, text.text * _homebrew_packages.prefix_ - Homebrew install prefix @@ -4420,6 +4543,10 @@ For more information about osquery tables, see the https://osquery.io/schema[osq * _event_taps.process_being_tapped_ - The process ID of the target application +*process_sequence_number* - keyword, number.long + +* _process_etw_events.process_sequence_number_ - Process Sequence Number - Present only on ProcessStart events + *process_type* - keyword, text.text * _launchd.process_type_ - Key describes the intended purpose of the job @@ -4444,6 +4571,10 @@ For more information about osquery tables, see the https://osquery.io/schema[osq * _cpu_info.processor_type_ - The processor type, such as Central, Math, or Video. +*product_id* - keyword, text.text + +* _connected_displays.product_id_ - The product ID of the display. + *product_name* - keyword, text.text * _tpm_info.product_name_ - Product name of the TPM @@ -4487,6 +4618,10 @@ For more information about osquery tables, see the https://osquery.io/schema[osq * _docker_container_mounts.propagation_ - Mount propagation +*properties* - keyword, text.text + +* _windows_search.properties_ - Additional property values JSON + *protected* - keyword, number.long * _app_schemes.protected_ - 1 if this handler is protected (reserved) by macOS, else 0 @@ -4554,6 +4689,7 @@ For more information about osquery tables, see the https://osquery.io/schema[osq * _mdfind.query_ - The query that was run to find the file * _osquery_schedule.query_ - The exact query to run +* _windows_search.query_ - Windows search query * _wmi_event_filters.query_ - Windows Management Instrumentation Query Language (WQL) event query that specifies the set of events for consumer notification, and the specific conditions for notification. *query_language* - keyword, text.text @@ -4761,6 +4897,10 @@ For more information about osquery tables, see the https://osquery.io/schema[osq * _docker_container_processes.resident_size_ - Bytes of private memory used by process * _processes.resident_size_ - Bytes of private memory used by process +*resolution* - keyword, text.text + +* _connected_displays.resolution_ - The resolution of the display. + *resource_group_name* - keyword, text.text * _azure_instance_metadata.resource_group_name_ - Resource group for the VM @@ -4829,6 +4969,10 @@ For more information about osquery tables, see the https://osquery.io/schema[osq * _time_machine_destinations.root_volume_uuid_ - Root UUID of backup volume +*rotation* - keyword, text.text + +* _connected_displays.rotation_ - The orientation of the display. + *round_trip_time* - keyword, number.long * _curl.round_trip_time_ - Time taken to complete the request @@ -4933,6 +5077,10 @@ For more information about osquery tables, see the https://osquery.io/schema[osq * _secureboot.secure_boot_ - Whether secure boot is enabled +*secure_mode* - keyword, number.long + +* _secureboot.secure_mode_ - Secure mode for Intel-based macOS: 0 disabled, 1 full security, 2 medium security + *secure_process* - keyword, number.long * _processes.secure_process_ - Process is secure (IUM) yes=1, no=0 @@ -4992,7 +5140,9 @@ For more information about osquery tables, see the https://osquery.io/schema[osq * _authenticode.serial_number_ - The certificate serial number * _battery.serial_number_ - The battery's unique serial number +* _connected_displays.serial_number_ - The serial number of the display. (may not be unique) * _curl_certificate.serial_number_ - Certificate serial number +* _kernel_keys.serial_number_ - The serial key of the key. * _memory_devices.serial_number_ - Serial number of memory device *serial_port_enabled* - keyword, text.text @@ -5049,6 +5199,7 @@ For more information about osquery tables, see the https://osquery.io/schema[osq *session_id* - keyword, number.long * _logon_sessions.session_id_ - The Terminal Services session identifier. +* _process_etw_events.session_id_ - Session ID * _winbaseobj.session_id_ - Terminal Services Session Id *session_owner* - keyword, text.text @@ -5206,6 +5357,7 @@ For more information about osquery tables, see the https://osquery.io/schema[osq * _shared_memory.size_ - Size in bytes * _smbios_tables.size_ - Table entry size in bytes * _smc_keys.size_ - Reported size of data in bytes +* _windows_search.size_ - The item size in bytes. *size_bytes* - keyword, number.long @@ -5243,6 +5395,10 @@ For more information about osquery tables, see the https://osquery.io/schema[osq * _cpu_time.softirq_ - Time spent servicing softirqs +*sort* - keyword, text.text + +* _windows_search.sort_ - Sort for windows api + *source* - keyword, text.text * _apt_sources.source_ - Source file @@ -5693,6 +5849,7 @@ For more information about osquery tables, see the https://osquery.io/schema[osq * _ntfs_journal_events.time_ - Time of file event * _package_install_history.time_ - Label date as UNIX timestamp * _powershell_events.time_ - Timestamp the event was received by the osquery event publisher +* _process_etw_events.time_ - Event timestamp in Unix format * _process_events.time_ - Time of execution in UNIX time * _process_file_events.time_ - Time of execution in UNIX time * _seccomp_events.time_ - Time of execution in UNIX time @@ -5714,10 +5871,15 @@ For more information about osquery tables, see the https://osquery.io/schema[osq * _windows_eventlog.time_range_ - System time to selectively filter the events +*time_windows* - keyword, number.long + +* _process_etw_events.time_windows_ - Event timestamp in Windows format + *timeout* - keyword, text.text * _authorizations.timeout_ - Label top-level key * _curl_certificate.timeout_ - Set this value to the timeout in seconds to complete the TLS handshake (default 4s, use 0 for no timeout) +* _kernel_keys.timeout_ - The amount of time until the key will expire,expressed in human-readable form. The string perm heremeans that the key is permanent (no timeout). Thestring expd means that the key has already expired. *timestamp* - keyword, text.text @@ -5738,6 +5900,14 @@ For more information about osquery tables, see the https://osquery.io/schema[osq * _cups_jobs.title_ - Title of the printed job * _windows_update_history.title_ - Title of an update +*token_elevation_status* - keyword, number.long + +* _process_etw_events.token_elevation_status_ - Primary token elevation status - Present only on ProcessStart events + +*token_elevation_type* - keyword, text.text + +* _process_etw_events.token_elevation_type_ - Primary token elevation type - Present only on ProcessStart events + *total_seconds* - keyword, number.long * _uptime.total_seconds_ - Total uptime seconds @@ -5803,6 +5973,7 @@ For more information about osquery tables, see the https://osquery.io/schema[osq * _hardware_events.type_ - Type of hardware and hardware event * _interface_addresses.type_ - Type of address. One of dhcp, manual, auto, other, unknown * _interface_details.type_ - Interface type (includes virtual) +* _kernel_keys.type_ - The key type. * _keychain_items.type_ - Keychain item type (class) * _last.type_ - Entry type, according to ut_type types (utmp.h) * _logged_in_users.type_ - Login type @@ -5815,6 +5986,7 @@ For more information about osquery tables, see the https://osquery.io/schema[osq * _osquery_events.type_ - Either publisher or subscriber * _osquery_extensions.type_ - SDK extension type: core, extension, or module * _osquery_flags.type_ - Flag type +* _process_etw_events.type_ - Event Type (ProcessStart, ProcessStop) * _process_open_pipes.type_ - Pipe Type: named vs unnamed/anonymous * _registry.type_ - Type of the registry value, or 'subkey' if item is a subkey * _routes.type_ - Type of route @@ -5828,6 +6000,7 @@ For more information about osquery tables, see the https://osquery.io/schema[osq * _user_events.type_ - The file description for the process socket * _users.type_ - Whether the account is roaming (domain), local, or a system profile * _windows_crashes.type_ - Type of crash log +* _windows_search.type_ - The item type * _windows_security_products.type_ - Type of security product * _xprotect_meta.type_ - Either plugin or extension @@ -5855,6 +6028,7 @@ For more information about osquery tables, see the https://osquery.io/schema[osq * _file.uid_ - Owning user ID * _file_events.uid_ - Owning user ID * _firefox_addons.uid_ - The local user that owns the addon +* _kernel_keys.uid_ - The user ID of the key owner. * _known_hosts.uid_ - The local user that owns the known_hosts file * _launchd_overrides.uid_ - User ID applied to the override, 0 applies to all * _package_bom.uid_ - Expected user of file or directory @@ -5891,6 +6065,10 @@ For more information about osquery tables, see the https://osquery.io/schema[osq * _ibridge_info.unique_chip_id_ - Unique id of the iBridge controller +*unit_file_state* - keyword, text.text + +* _systemd_units.unit_file_state_ - Whether the unit file is enabled, e.g. `enabled`, `masked`, `disabled`, etc + *unix_time* - keyword, number.long * _time.unix_time_ - Current UNIX time in UTC @@ -5964,6 +6142,10 @@ For more information about osquery tables, see the https://osquery.io/schema[osq * _curl.url_ - The url for the request * _lxd_cluster_members.url_ - URL of the node +*usage* - keyword, number.long + +* _kernel_keys.usage_ - the number of threads and open file references thatrefer to this key. + *usb_address* - keyword, number.long * _usb_devices.usb_address_ - USB Device used address @@ -6030,6 +6212,7 @@ For more information about osquery tables, see the https://osquery.io/schema[osq * _launchd.username_ - Run this daemon or agent as this username * _managed_policies.username_ - Policy applies only this user * _preferences.username_ - (optional) read preferences for a specific user +* _process_etw_events.username_ - User rights - primary token username * _rpm_package_files.username_ - File default username from info DB * _shadow.username_ - Username * _startup_items.username_ - The user associated with the startup item @@ -6119,6 +6302,7 @@ For more information about osquery tables, see the https://osquery.io/schema[osq *vendor_id* - keyword, text.text +* _connected_displays.vendor_id_ - The vendor ID of the display. * _hardware_events.vendor_id_ - Hex encoded Hardware vendor identifier * _pci_devices.vendor_id_ - Hex encoded PCI Device vendor identifier * _usb_devices.vendor_id_ - Hex encoded USB Device vendor identifier diff --git a/examples/bfetch_explorer/server/index.ts b/examples/bfetch_explorer/server/index.ts index 4dd6223251dc3..6f80829362d6b 100644 --- a/examples/bfetch_explorer/server/index.ts +++ b/examples/bfetch_explorer/server/index.ts @@ -6,6 +6,7 @@ * Side Public License, v 1. */ -import { BfetchExplorerPlugin } from './plugin'; - -export const plugin = () => new BfetchExplorerPlugin(); +export const plugin = async () => { + const { BfetchExplorerPlugin } = await import('./plugin'); + return new BfetchExplorerPlugin(); +}; diff --git a/examples/content_management_examples/server/index.ts b/examples/content_management_examples/server/index.ts index d75af7bacf224..069a36852fca7 100644 --- a/examples/content_management_examples/server/index.ts +++ b/examples/content_management_examples/server/index.ts @@ -7,8 +7,8 @@ */ import { PluginInitializerContext } from '@kbn/core/server'; -import { ContentManagementExamplesPlugin } from './plugin'; -export function plugin(initializerContext: PluginInitializerContext) { +export async function plugin(initializerContext: PluginInitializerContext) { + const { ContentManagementExamplesPlugin } = await import('./plugin'); return new ContentManagementExamplesPlugin(initializerContext); } diff --git a/examples/embeddable_examples/server/index.ts b/examples/embeddable_examples/server/index.ts index 0139633a71d69..cb0e20e34042e 100644 --- a/examples/embeddable_examples/server/index.ts +++ b/examples/embeddable_examples/server/index.ts @@ -8,6 +8,7 @@ import { PluginInitializer } from '@kbn/core/server'; -import { EmbeddableExamplesPlugin } from './plugin'; - -export const plugin: PluginInitializer = () => new EmbeddableExamplesPlugin(); +export const plugin: PluginInitializer = async () => { + const { EmbeddableExamplesPlugin } = await import('./plugin'); + return new EmbeddableExamplesPlugin(); +}; diff --git a/examples/feature_control_examples/server/index.ts b/examples/feature_control_examples/server/index.ts index 0db874ff2047e..20cf4e280ca45 100644 --- a/examples/feature_control_examples/server/index.ts +++ b/examples/feature_control_examples/server/index.ts @@ -6,6 +6,8 @@ * Side Public License, v 1. */ import { PluginInitializer } from '@kbn/core/server'; -import { FeatureControlsPluginExample } from './plugin'; -export const plugin: PluginInitializer = () => new FeatureControlsPluginExample(); +export const plugin: PluginInitializer = async () => { + const { FeatureControlsPluginExample } = await import('./plugin'); + return new FeatureControlsPluginExample(); +}; diff --git a/examples/field_formats_example/server/index.ts b/examples/field_formats_example/server/index.ts index cd8ee4c30b63a..63537dc1393fe 100644 --- a/examples/field_formats_example/server/index.ts +++ b/examples/field_formats_example/server/index.ts @@ -6,8 +6,7 @@ * Side Public License, v 1. */ -import { FieldFormatsExamplePlugin } from './plugin'; - -export function plugin() { +export async function plugin() { + const { FieldFormatsExamplePlugin } = await import('./plugin'); return new FieldFormatsExamplePlugin(); } diff --git a/examples/files_example/server/index.ts b/examples/files_example/server/index.ts index d7edefbe1876d..0ca8a663aa7f5 100644 --- a/examples/files_example/server/index.ts +++ b/examples/files_example/server/index.ts @@ -7,11 +7,11 @@ */ import { PluginInitializerContext } from '@kbn/core/server'; -import { FilesExamplePlugin } from './plugin'; // This exports static code and TypeScript types, // as well as, Kibana Platform `plugin()` initializer. -export function plugin(initializerContext: PluginInitializerContext) { +export async function plugin(initializerContext: PluginInitializerContext) { + const { FilesExamplePlugin } = await import('./plugin'); return new FilesExamplePlugin(initializerContext); } diff --git a/examples/guided_onboarding_example/server/index.ts b/examples/guided_onboarding_example/server/index.ts index dbcdfe70c67ee..a70d488d29236 100644 --- a/examples/guided_onboarding_example/server/index.ts +++ b/examples/guided_onboarding_example/server/index.ts @@ -7,6 +7,8 @@ */ import { PluginInitializerContext } from '@kbn/core/server'; -import { GuidedOnboardingExamplePlugin } from './plugin'; -export const plugin = (ctx: PluginInitializerContext) => new GuidedOnboardingExamplePlugin(ctx); +export const plugin = async (ctx: PluginInitializerContext) => { + const { GuidedOnboardingExamplePlugin } = await import('./plugin'); + return new GuidedOnboardingExamplePlugin(ctx); +}; diff --git a/examples/preboot_example/server/index.ts b/examples/preboot_example/server/index.ts index cc231e0c873ed..b5442168f99ab 100644 --- a/examples/preboot_example/server/index.ts +++ b/examples/preboot_example/server/index.ts @@ -10,11 +10,13 @@ import type { TypeOf } from '@kbn/config-schema'; import type { PluginConfigDescriptor, PluginInitializerContext } from '@kbn/core/server'; import { ConfigSchema } from './config'; -import { PrebootExamplePlugin } from './plugin'; export const config: PluginConfigDescriptor> = { schema: ConfigSchema, exposeToBrowser: { token: true }, }; -export const plugin = (context: PluginInitializerContext) => new PrebootExamplePlugin(context); +export const plugin = async (context: PluginInitializerContext) => { + const { PrebootExamplePlugin } = await import('./plugin'); + return new PrebootExamplePlugin(context); +}; diff --git a/examples/response_stream/server/index.ts b/examples/response_stream/server/index.ts index 2d1bb6229fce4..9f6fd17f56ae1 100644 --- a/examples/response_stream/server/index.ts +++ b/examples/response_stream/server/index.ts @@ -8,8 +8,7 @@ import { PluginInitializerContext } from '@kbn/core/server'; -import { ResponseStreamPlugin } from './plugin'; - -export function plugin(initializerContext: PluginInitializerContext) { +export async function plugin(initializerContext: PluginInitializerContext) { + const { ResponseStreamPlugin } = await import('./plugin'); return new ResponseStreamPlugin(initializerContext); } diff --git a/examples/routing_example/server/index.ts b/examples/routing_example/server/index.ts index 1fc65c6da1314..fd5a8f2680c0d 100644 --- a/examples/routing_example/server/index.ts +++ b/examples/routing_example/server/index.ts @@ -8,6 +8,7 @@ import { PluginInitializer } from '@kbn/core/server'; -import { RoutingExamplePlugin } from './plugin'; - -export const plugin: PluginInitializer<{}, {}> = () => new RoutingExamplePlugin(); +export const plugin: PluginInitializer<{}, {}> = async () => { + const { RoutingExamplePlugin } = await import('./plugin'); + return new RoutingExamplePlugin(); +}; diff --git a/examples/screenshot_mode_example/server/index.ts b/examples/screenshot_mode_example/server/index.ts index 3237dbabff937..e383939cf7281 100644 --- a/examples/screenshot_mode_example/server/index.ts +++ b/examples/screenshot_mode_example/server/index.ts @@ -7,6 +7,8 @@ */ import { PluginInitializerContext } from '@kbn/core/server'; -import { ScreenshotModeExamplePlugin } from './plugin'; -export const plugin = (ctx: PluginInitializerContext) => new ScreenshotModeExamplePlugin(ctx); +export const plugin = async (ctx: PluginInitializerContext) => { + const { ScreenshotModeExamplePlugin } = await import('./plugin'); + return new ScreenshotModeExamplePlugin(ctx); +}; diff --git a/examples/search_examples/server/index.ts b/examples/search_examples/server/index.ts index 1b1f69bcb32aa..211bdb658b590 100644 --- a/examples/search_examples/server/index.ts +++ b/examples/search_examples/server/index.ts @@ -7,9 +7,9 @@ */ import { PluginInitializerContext } from '@kbn/core/server'; -import { SearchExamplesPlugin } from './plugin'; -export function plugin(initializerContext: PluginInitializerContext) { +export async function plugin(initializerContext: PluginInitializerContext) { + const { SearchExamplesPlugin } = await import('./plugin'); return new SearchExamplesPlugin(initializerContext); } diff --git a/examples/user_profile_examples/server/index.ts b/examples/user_profile_examples/server/index.ts index 7b5e8eb32a645..6929bd5c6bb0e 100755 --- a/examples/user_profile_examples/server/index.ts +++ b/examples/user_profile_examples/server/index.ts @@ -5,6 +5,8 @@ * in compliance with, at your election, the Elastic License 2.0 or the Server * Side Public License, v 1. */ -import { UserProfilesPlugin } from './plugin'; -export const plugin = () => new UserProfilesPlugin(); +export const plugin = async () => { + const { UserProfilesPlugin } = await import('./plugin'); + return new UserProfilesPlugin(); +}; diff --git a/examples/v8_profiler_examples/server/index.ts b/examples/v8_profiler_examples/server/index.ts index d06809f7411b5..f917a93ebd5f1 100644 --- a/examples/v8_profiler_examples/server/index.ts +++ b/examples/v8_profiler_examples/server/index.ts @@ -7,8 +7,8 @@ */ import { PluginInitializerContext } from '@kbn/core/server'; -import { V8ProfilerExamplesPlugin } from './plugin'; -export function plugin(initializerContext: PluginInitializerContext) { +export async function plugin(initializerContext: PluginInitializerContext) { + const { V8ProfilerExamplesPlugin } = await import('./plugin'); return new V8ProfilerExamplesPlugin(initializerContext); } diff --git a/package.json b/package.json index 5b1c5acbc476f..35c4197f57181 100644 --- a/package.json +++ b/package.json @@ -450,7 +450,6 @@ "@kbn/gen-ai-streaming-response-example-plugin": "link:x-pack/examples/gen_ai_streaming_response_example", "@kbn/generate-console-definitions": "link:packages/kbn-generate-console-definitions", "@kbn/generate-csv": "link:packages/kbn-generate-csv", - "@kbn/generate-csv-types": "link:packages/kbn-generate-csv-types", "@kbn/global-search-bar-plugin": "link:x-pack/plugins/global_search_bar", "@kbn/global-search-plugin": "link:x-pack/plugins/global_search", "@kbn/global-search-providers-plugin": "link:x-pack/plugins/global_search_providers", @@ -597,7 +596,16 @@ "@kbn/repo-packages": "link:packages/kbn-repo-packages", "@kbn/reporting-common": "link:packages/kbn-reporting/common", "@kbn/reporting-example-plugin": "link:x-pack/examples/reporting_example", + "@kbn/reporting-export-types-csv": "link:packages/kbn-reporting/export_types/csv", + "@kbn/reporting-export-types-csv-common": "link:packages/kbn-reporting/export_types/csv_common", + "@kbn/reporting-export-types-pdf": "link:packages/kbn-reporting/export_types/pdf", + "@kbn/reporting-export-types-pdf-common": "link:packages/kbn-reporting/export_types/pdf_common", + "@kbn/reporting-export-types-png": "link:packages/kbn-reporting/export_types/png", + "@kbn/reporting-export-types-png-common": "link:packages/kbn-reporting/export_types/png_common", + "@kbn/reporting-mocks-server": "link:packages/kbn-reporting/mocks_server", "@kbn/reporting-plugin": "link:x-pack/plugins/reporting", + "@kbn/reporting-public": "link:packages/kbn-reporting/public", + "@kbn/reporting-server": "link:packages/kbn-reporting/server", "@kbn/resizable-layout": "link:packages/kbn-resizable-layout", "@kbn/resizable-layout-examples-plugin": "link:examples/resizable_layout_examples", "@kbn/resolver-test-plugin": "link:x-pack/test/plugin_functional/plugins/resolver_test", @@ -1446,7 +1454,7 @@ "apidoc-markdown": "^7.2.4", "argsplit": "^1.0.5", "autoprefixer": "^10.4.7", - "axe-core": "^4.6.1", + "axe-core": "^4.8.2", "babel-jest": "^29.6.1", "babel-loader": "^8.2.5", "babel-plugin-add-module-exports": "^1.0.4", diff --git a/packages/core/application/core-application-browser-internal/src/application_service.tsx b/packages/core/application/core-application-browser-internal/src/application_service.tsx index d54b71b91f119..8e5f2643929e7 100644 --- a/packages/core/application/core-application-browser-internal/src/application_service.tsx +++ b/packages/core/application/core-application-browser-internal/src/application_service.tsx @@ -13,7 +13,7 @@ import { createBrowserHistory, History } from 'history'; import type { PluginOpaqueId } from '@kbn/core-base-common'; import type { ThemeServiceStart } from '@kbn/core-theme-browser'; -import type { HttpSetup, HttpStart } from '@kbn/core-http-browser'; +import type { InternalHttpSetup, InternalHttpStart } from '@kbn/core-http-browser-internal'; import type { Capabilities } from '@kbn/core-capabilities-common'; import type { MountPoint } from '@kbn/core-mount-utils-browser'; import type { OverlayStart } from '@kbn/core-overlays-browser'; @@ -46,7 +46,7 @@ import { import { registerAnalyticsContextProvider } from './register_analytics_context_provider'; export interface SetupDeps { - http: HttpSetup; + http: InternalHttpSetup; analytics: AnalyticsServiceSetup; history?: History; /** Used to redirect to external urls */ @@ -54,7 +54,7 @@ export interface SetupDeps { } export interface StartDeps { - http: HttpStart; + http: InternalHttpStart; analytics: AnalyticsServiceStart; theme: ThemeServiceStart; overlays: OverlayStart; diff --git a/packages/core/application/core-application-browser-internal/src/utils/parse_app_url.test.ts b/packages/core/application/core-application-browser-internal/src/utils/parse_app_url.test.ts index 7bc5752a72b13..0126acd36e453 100644 --- a/packages/core/application/core-application-browser-internal/src/utils/parse_app_url.test.ts +++ b/packages/core/application/core-application-browser-internal/src/utils/parse_app_url.test.ts @@ -30,7 +30,7 @@ describe('parseAppUrl', () => { beforeEach(() => { apps = new Map(); - basePath = new BasePath('/base-path'); + basePath = new BasePath({ basePath: '/base-path' }); createApp({ id: 'foo', diff --git a/packages/core/apps/core-apps-browser-internal/src/core_app.ts b/packages/core/apps/core-apps-browser-internal/src/core_app.ts index e8a61de40bea2..c6a8583a14930 100644 --- a/packages/core/apps/core-apps-browser-internal/src/core_app.ts +++ b/packages/core/apps/core-apps-browser-internal/src/core_app.ts @@ -10,7 +10,7 @@ import type { UnregisterCallback } from 'history'; import type { CoreContext } from '@kbn/core-base-browser-internal'; import type { InternalInjectedMetadataSetup } from '@kbn/core-injected-metadata-browser-internal'; import type { DocLinksStart } from '@kbn/core-doc-links-browser'; -import type { HttpSetup, HttpStart } from '@kbn/core-http-browser'; +import type { InternalHttpSetup, InternalHttpStart } from '@kbn/core-http-browser-internal'; import type { IUiSettingsClient } from '@kbn/core-ui-settings-browser'; import type { NotificationsSetup, NotificationsStart } from '@kbn/core-notifications-browser'; import { AppNavLinkStatus, type AppMountParameters } from '@kbn/core-application-browser'; @@ -27,7 +27,7 @@ import { renderApp as renderStatusApp } from './status'; export interface CoreAppsServiceSetupDeps { application: InternalApplicationSetup; - http: HttpSetup; + http: InternalHttpSetup; injectedMetadata: InternalInjectedMetadataSetup; notifications: NotificationsSetup; } @@ -35,7 +35,7 @@ export interface CoreAppsServiceSetupDeps { export interface CoreAppsServiceStartDeps { application: InternalApplicationStart; docLinks: DocLinksStart; - http: HttpStart; + http: InternalHttpStart; notifications: NotificationsStart; uiSettings: IUiSettingsClient; } diff --git a/packages/core/apps/core-apps-browser-internal/src/errors/error_application.test.ts b/packages/core/apps/core-apps-browser-internal/src/errors/error_application.test.ts index 5ca92bc3904f4..65f7a437631b1 100644 --- a/packages/core/apps/core-apps-browser-internal/src/errors/error_application.test.ts +++ b/packages/core/apps/core-apps-browser-internal/src/errors/error_application.test.ts @@ -22,7 +22,7 @@ describe('renderApp', () => { let unmount: () => void; beforeEach(() => { - basePath = new BasePath(); + basePath = new BasePath({ basePath: '' }); element = document.createElement('div'); history = createMemoryHistory(); unmount = renderApp( diff --git a/packages/core/apps/core-apps-browser-internal/src/errors/public_base_url.tsx b/packages/core/apps/core-apps-browser-internal/src/errors/public_base_url.tsx index 0d2e678963d8b..f125d03239802 100644 --- a/packages/core/apps/core-apps-browser-internal/src/errors/public_base_url.tsx +++ b/packages/core/apps/core-apps-browser-internal/src/errors/public_base_url.tsx @@ -12,7 +12,7 @@ import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n-react'; import type { DocLinksStart } from '@kbn/core-doc-links-browser'; -import type { HttpStart } from '@kbn/core-http-browser'; +import type { InternalHttpStart } from '@kbn/core-http-browser-internal'; import type { NotificationsStart } from '@kbn/core-notifications-browser'; import { mountReactNode } from '@kbn/core-mount-utils-browser-internal'; @@ -21,7 +21,7 @@ export const MISSING_CONFIG_STORAGE_KEY = `core.warnings.publicBaseUrlMissingDis interface Deps { docLinks: DocLinksStart; - http: HttpStart; + http: InternalHttpStart; notifications: NotificationsStart; // Exposed for easier testing storage?: Storage; diff --git a/packages/core/apps/core-apps-browser-internal/src/errors/url_overflow.test.ts b/packages/core/apps/core-apps-browser-internal/src/errors/url_overflow.test.ts index bdf8bdf0abc6a..dae718c75afce 100644 --- a/packages/core/apps/core-apps-browser-internal/src/errors/url_overflow.test.ts +++ b/packages/core/apps/core-apps-browser-internal/src/errors/url_overflow.test.ts @@ -27,7 +27,7 @@ describe('url overflow detection', () => { let unlisten: any; beforeEach(() => { - basePath = new BasePath('/test-123'); + basePath = new BasePath({ basePath: '/test-123' }); history = createMemoryHistory(); toasts = notificationServiceMock.createStartContract().toasts; uiSettings = uiSettingsServiceMock.createStartContract(); diff --git a/packages/core/apps/core-apps-browser-internal/src/status/lib/load_status.ts b/packages/core/apps/core-apps-browser-internal/src/status/lib/load_status.ts index 6672786c72a10..7338db04716c0 100644 --- a/packages/core/apps/core-apps-browser-internal/src/status/lib/load_status.ts +++ b/packages/core/apps/core-apps-browser-internal/src/status/lib/load_status.ts @@ -189,7 +189,7 @@ export async function loadStatus({ http, notifications, }: { - http: HttpSetup; + http: Pick; notifications: NotificationsSetup; }) { let response: StatusResponse; diff --git a/packages/core/apps/core-apps-browser-internal/src/status/render_app.tsx b/packages/core/apps/core-apps-browser-internal/src/status/render_app.tsx index 4578ff0f347d6..a2af773a239ad 100644 --- a/packages/core/apps/core-apps-browser-internal/src/status/render_app.tsx +++ b/packages/core/apps/core-apps-browser-internal/src/status/render_app.tsx @@ -10,13 +10,13 @@ import React from 'react'; import ReactDOM from 'react-dom'; import { I18nProvider } from '@kbn/i18n-react'; import { CoreThemeProvider } from '@kbn/core-theme-browser-internal'; -import type { HttpSetup } from '@kbn/core-http-browser'; +import type { InternalHttpSetup } from '@kbn/core-http-browser-internal'; import type { NotificationsSetup } from '@kbn/core-notifications-browser'; import type { AppMountParameters } from '@kbn/core-application-browser'; import { StatusApp } from './status_app'; interface Deps { - http: HttpSetup; + http: InternalHttpSetup; notifications: NotificationsSetup; } diff --git a/packages/core/apps/core-apps-browser-internal/src/status/status_app.tsx b/packages/core/apps/core-apps-browser-internal/src/status/status_app.tsx index 43e388ad170a8..88ae96bd33596 100644 --- a/packages/core/apps/core-apps-browser-internal/src/status/status_app.tsx +++ b/packages/core/apps/core-apps-browser-internal/src/status/status_app.tsx @@ -10,13 +10,13 @@ import React, { Component } from 'react'; import { EuiLoadingSpinner, EuiText, EuiPage, EuiPageBody, EuiSpacer } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n-react'; import { i18n } from '@kbn/i18n'; -import type { HttpSetup } from '@kbn/core-http-browser'; +import type { InternalHttpSetup } from '@kbn/core-http-browser-internal'; import type { NotificationsSetup } from '@kbn/core-notifications-browser'; import { loadStatus, type ProcessedServerResponse } from './lib'; import { MetricTiles, ServerStatus, StatusSection, VersionHeader } from './components'; interface StatusAppProps { - http: HttpSetup; + http: InternalHttpSetup; notifications: NotificationsSetup; } diff --git a/packages/core/capabilities/core-capabilities-browser-internal/src/capabilities_service.tsx b/packages/core/capabilities/core-capabilities-browser-internal/src/capabilities_service.tsx index 746911117e5ab..0751225af5311 100644 --- a/packages/core/capabilities/core-capabilities-browser-internal/src/capabilities_service.tsx +++ b/packages/core/capabilities/core-capabilities-browser-internal/src/capabilities_service.tsx @@ -8,12 +8,12 @@ import type { RecursiveReadonly } from '@kbn/utility-types'; import { deepFreeze } from '@kbn/std'; -import type { HttpStart } from '@kbn/core-http-browser'; +import type { InternalHttpStart } from '@kbn/core-http-browser-internal'; import type { Capabilities } from '@kbn/core-capabilities-common'; interface StartDeps { appIds: string[]; - http: HttpStart; + http: InternalHttpStart; } /** @internal */ diff --git a/packages/core/capabilities/core-capabilities-browser-internal/tsconfig.json b/packages/core/capabilities/core-capabilities-browser-internal/tsconfig.json index 258f96a51d15b..ca9379c024865 100644 --- a/packages/core/capabilities/core-capabilities-browser-internal/tsconfig.json +++ b/packages/core/capabilities/core-capabilities-browser-internal/tsconfig.json @@ -14,9 +14,9 @@ "kbn_references": [ "@kbn/utility-types", "@kbn/std", - "@kbn/core-http-browser", "@kbn/core-http-browser-mocks", - "@kbn/core-capabilities-common" + "@kbn/core-capabilities-common", + "@kbn/core-http-browser-internal" ], "exclude": [ "target/**/*", 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 eaa30238cde89..e7f1ecbd29acc 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 @@ -16,7 +16,7 @@ import useObservable from 'react-use/lib/useObservable'; import type { InternalInjectedMetadataStart } from '@kbn/core-injected-metadata-browser-internal'; import type { AnalyticsServiceSetup } from '@kbn/core-analytics-browser'; import { type DocLinksStart } from '@kbn/core-doc-links-browser'; -import type { HttpStart } from '@kbn/core-http-browser'; +import type { InternalHttpStart } from '@kbn/core-http-browser-internal'; import { mountReactNode } from '@kbn/core-mount-utils-browser-internal'; import type { NotificationsStart } from '@kbn/core-notifications-browser'; import type { InternalApplicationStart } from '@kbn/core-application-browser-internal'; @@ -63,7 +63,7 @@ export interface SetupDeps { export interface StartDeps { application: InternalApplicationStart; docLinks: DocLinksStart; - http: HttpStart; + http: InternalHttpStart; injectedMetadata: InternalInjectedMetadataStart; notifications: NotificationsStart; customBranding: CustomBrandingStart; diff --git a/packages/core/chrome/core-chrome-browser-internal/src/nav_links/nav_links_service.ts b/packages/core/chrome/core-chrome-browser-internal/src/nav_links/nav_links_service.ts index e55e8cd0307a9..08466a1f35fb0 100644 --- a/packages/core/chrome/core-chrome-browser-internal/src/nav_links/nav_links_service.ts +++ b/packages/core/chrome/core-chrome-browser-internal/src/nav_links/nav_links_service.ts @@ -9,7 +9,8 @@ import { sortBy } from 'lodash'; import { BehaviorSubject, ReplaySubject } from 'rxjs'; import { map, takeUntil } from 'rxjs/operators'; -import type { HttpStart, IBasePath } from '@kbn/core-http-browser'; +import type { IBasePath } from '@kbn/core-http-browser'; +import type { InternalHttpStart } from '@kbn/core-http-browser-internal'; import type { PublicAppDeepLinkInfo, PublicAppInfo } from '@kbn/core-application-browser'; import type { InternalApplicationStart } from '@kbn/core-application-browser-internal'; import type { ChromeNavLinks } from '@kbn/core-chrome-browser'; @@ -18,7 +19,7 @@ import { toNavLink } from './to_nav_link'; interface StartDeps { application: InternalApplicationStart; - http: HttpStart; + http: InternalHttpStart; } export class NavLinksService { diff --git a/packages/core/chrome/core-chrome-browser-internal/src/project_navigation/project_navigation_service.ts b/packages/core/chrome/core-chrome-browser-internal/src/project_navigation/project_navigation_service.ts index 38766a026cdcc..7a8f5b89db653 100644 --- a/packages/core/chrome/core-chrome-browser-internal/src/project_navigation/project_navigation_service.ts +++ b/packages/core/chrome/core-chrome-browser-internal/src/project_navigation/project_navigation_service.ts @@ -16,7 +16,7 @@ import { ChromeSetProjectBreadcrumbsParams, ChromeProjectNavigationNode, } from '@kbn/core-chrome-browser'; -import type { HttpStart } from '@kbn/core-http-browser'; +import type { InternalHttpStart } from '@kbn/core-http-browser-internal'; import { BehaviorSubject, Observable, @@ -37,7 +37,7 @@ import { buildBreadcrumbs } from './breadcrumbs'; interface StartDeps { application: InternalApplicationStart; navLinks: ChromeNavLinks; - http: HttpStart; + http: InternalHttpStart; chromeBreadcrumbs$: Observable; } @@ -59,7 +59,7 @@ export class ProjectNavigationService { }>({ breadcrumbs: [], params: { absolute: false } }); private readonly stop$ = new ReplaySubject(1); private application?: InternalApplicationStart; - private http?: HttpStart; + private http?: InternalHttpStart; private unlistenHistory?: () => void; public start({ application, navLinks, http, chromeBreadcrumbs$ }: StartDeps) { diff --git a/packages/core/chrome/core-chrome-browser-internal/src/recently_accessed/recently_accessed_service.ts b/packages/core/chrome/core-chrome-browser-internal/src/recently_accessed/recently_accessed_service.ts index 414f0c796d1bd..ec9a04ab5551c 100644 --- a/packages/core/chrome/core-chrome-browser-internal/src/recently_accessed/recently_accessed_service.ts +++ b/packages/core/chrome/core-chrome-browser-internal/src/recently_accessed/recently_accessed_service.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import type { HttpSetup } from '@kbn/core-http-browser'; +import type { InternalHttpStart } from '@kbn/core-http-browser-internal'; import type { ChromeRecentlyAccessed, ChromeRecentlyAccessedHistoryItem, @@ -15,7 +15,7 @@ import { PersistedLog } from './persisted_log'; import { createLogKey } from './create_log_key'; interface StartDeps { - http: HttpSetup; + http: InternalHttpStart; } /** @internal */ diff --git a/packages/core/chrome/core-chrome-browser-internal/src/ui/header/__snapshots__/collapsible_nav.test.tsx.snap b/packages/core/chrome/core-chrome-browser-internal/src/ui/header/__snapshots__/collapsible_nav.test.tsx.snap index c5c82c88c8521..416ce39bbf9ba 100644 --- a/packages/core/chrome/core-chrome-browser-internal/src/ui/header/__snapshots__/collapsible_nav.test.tsx.snap +++ b/packages/core/chrome/core-chrome-browser-internal/src/ui/header/__snapshots__/collapsible_nav.test.tsx.snap @@ -733,6 +733,7 @@ exports[`CollapsibleNav renders the default nav 1`] = ` } basePath={ BasePath { + "assetsHrefBase": "/test", "basePath": "/test", "get": [Function], "prepend": [Function], @@ -918,6 +919,7 @@ exports[`CollapsibleNav renders the default nav 2`] = ` } basePath={ BasePath { + "assetsHrefBase": "/test", "basePath": "/test", "get": [Function], "prepend": [Function], diff --git a/packages/core/chrome/core-chrome-browser-internal/tsconfig.json b/packages/core/chrome/core-chrome-browser-internal/tsconfig.json index 020324c1f67bc..ed460a1965667 100644 --- a/packages/core/chrome/core-chrome-browser-internal/tsconfig.json +++ b/packages/core/chrome/core-chrome-browser-internal/tsconfig.json @@ -43,6 +43,7 @@ "@kbn/core-analytics-browser", "@kbn/shared-ux-router", "@kbn/shared-ux-link-redirect-app", + "@kbn/core-http-browser-internal", ], "exclude": [ "target/**/*", diff --git a/packages/core/deprecations/core-deprecations-browser-internal/src/deprecations_service.ts b/packages/core/deprecations/core-deprecations-browser-internal/src/deprecations_service.ts index edaf5f7f27be0..6dd78c8525f5d 100644 --- a/packages/core/deprecations/core-deprecations-browser-internal/src/deprecations_service.ts +++ b/packages/core/deprecations/core-deprecations-browser-internal/src/deprecations_service.ts @@ -8,13 +8,13 @@ import type { CoreService } from '@kbn/core-base-browser-internal'; import type { DeprecationsServiceStart } from '@kbn/core-deprecations-browser'; -import type { HttpStart } from '@kbn/core-http-browser'; +import type { InternalHttpStart } from '@kbn/core-http-browser-internal'; import { DeprecationsClient } from './deprecations_client'; export class DeprecationsService implements CoreService { public setup(): void {} - public start({ http }: { http: HttpStart }): DeprecationsServiceStart { + public start({ http }: { http: InternalHttpStart }): DeprecationsServiceStart { const deprecationsClient = new DeprecationsClient({ http }); return { diff --git a/packages/core/deprecations/core-deprecations-browser-internal/tsconfig.json b/packages/core/deprecations/core-deprecations-browser-internal/tsconfig.json index 8c7dde1c84e07..38fda3fdccf44 100644 --- a/packages/core/deprecations/core-deprecations-browser-internal/tsconfig.json +++ b/packages/core/deprecations/core-deprecations-browser-internal/tsconfig.json @@ -16,7 +16,8 @@ "@kbn/core-http-browser", "@kbn/core-http-browser-mocks", "@kbn/core-deprecations-common", - "@kbn/core-deprecations-browser" + "@kbn/core-deprecations-browser", + "@kbn/core-http-browser-internal" ], "exclude": [ "target/**/*", diff --git a/packages/core/elasticsearch/core-elasticsearch-client-server-internal/src/patch_client.ts b/packages/core/elasticsearch/core-elasticsearch-client-server-internal/src/patch_client.ts index 75ea5db91b2e3..a7bdf3788d2c8 100644 --- a/packages/core/elasticsearch/core-elasticsearch-client-server-internal/src/patch_client.ts +++ b/packages/core/elasticsearch/core-elasticsearch-client-server-internal/src/patch_client.ts @@ -6,6 +6,7 @@ * Side Public License, v 1. */ +import { inspect } from 'util'; import { errors } from '@elastic/elasticsearch'; export const patchElasticsearchClient = () => { @@ -17,4 +18,10 @@ export const patchElasticsearchClient = () => { message: this.message, }; }; + + // @ts-expect-error + baseErrorPrototype[inspect.custom] = function () { + // @ts-expect-error + return this.toJSON(); + }; }; diff --git a/packages/core/http/core-http-browser-internal/index.ts b/packages/core/http/core-http-browser-internal/index.ts index 3baa45b8bcdf1..0b747b6261eb9 100644 --- a/packages/core/http/core-http-browser-internal/index.ts +++ b/packages/core/http/core-http-browser-internal/index.ts @@ -8,3 +8,4 @@ export { BasePath } from './src/base_path'; export { HttpService } from './src/http_service'; +export type { InternalHttpSetup, InternalHttpStart } from './src/types'; diff --git a/packages/core/http/core-http-browser-internal/src/anonymous_paths_service.test.ts b/packages/core/http/core-http-browser-internal/src/anonymous_paths_service.test.ts index dff9c4719fef4..181641700d4d6 100644 --- a/packages/core/http/core-http-browser-internal/src/anonymous_paths_service.test.ts +++ b/packages/core/http/core-http-browser-internal/src/anonymous_paths_service.test.ts @@ -12,13 +12,13 @@ import { BasePath } from './base_path'; describe('#setup()', () => { describe('#register', () => { it(`allows paths that don't start with /`, () => { - const basePath = new BasePath('/foo'); + const basePath = new BasePath({ basePath: '/foo' }); const anonymousPaths = new AnonymousPathsService().setup({ basePath }); anonymousPaths.register('bar'); }); it(`allows paths that end with '/'`, () => { - const basePath = new BasePath('/foo'); + const basePath = new BasePath({ basePath: '/foo' }); const anonymousPaths = new AnonymousPathsService().setup({ basePath }); anonymousPaths.register('/bar/'); }); @@ -26,70 +26,70 @@ describe('#setup()', () => { describe('#isAnonymous', () => { it('returns true for registered paths', () => { - const basePath = new BasePath('/foo'); + const basePath = new BasePath({ basePath: '/foo' }); const anonymousPaths = new AnonymousPathsService().setup({ basePath }); anonymousPaths.register('/bar'); expect(anonymousPaths.isAnonymous('/foo/bar')).toBe(true); }); it('returns true for paths registered with a trailing slash, but call "isAnonymous" with no trailing slash', () => { - const basePath = new BasePath('/foo'); + const basePath = new BasePath({ basePath: '/foo' }); const anonymousPaths = new AnonymousPathsService().setup({ basePath }); anonymousPaths.register('/bar/'); expect(anonymousPaths.isAnonymous('/foo/bar')).toBe(true); }); it('returns true for paths registered without a trailing slash, but call "isAnonymous" with a trailing slash', () => { - const basePath = new BasePath('/foo'); + const basePath = new BasePath({ basePath: '/foo' }); const anonymousPaths = new AnonymousPathsService().setup({ basePath }); anonymousPaths.register('/bar'); expect(anonymousPaths.isAnonymous('/foo/bar/')).toBe(true); }); it('returns true for paths registered without a starting slash', () => { - const basePath = new BasePath('/foo'); + const basePath = new BasePath({ basePath: '/foo' }); const anonymousPaths = new AnonymousPathsService().setup({ basePath }); anonymousPaths.register('bar'); expect(anonymousPaths.isAnonymous('/foo/bar')).toBe(true); }); it('returns true for paths registered with a starting slash', () => { - const basePath = new BasePath('/foo'); + const basePath = new BasePath({ basePath: '/foo' }); const anonymousPaths = new AnonymousPathsService().setup({ basePath }); anonymousPaths.register('/bar'); expect(anonymousPaths.isAnonymous('/foo/bar')).toBe(true); }); it('when there is no basePath and calling "isAnonymous" without a starting slash, returns true for paths registered with a starting slash', () => { - const basePath = new BasePath('/'); + const basePath = new BasePath({ basePath: '/foo' }); const anonymousPaths = new AnonymousPathsService().setup({ basePath }); anonymousPaths.register('/bar'); expect(anonymousPaths.isAnonymous('bar')).toBe(true); }); it('when there is no basePath and calling "isAnonymous" with a starting slash, returns true for paths registered with a starting slash', () => { - const basePath = new BasePath('/'); + const basePath = new BasePath({ basePath: '/foo' }); const anonymousPaths = new AnonymousPathsService().setup({ basePath }); anonymousPaths.register('/bar'); expect(anonymousPaths.isAnonymous('/bar')).toBe(true); }); it('returns true for paths whose capitalization is different', () => { - const basePath = new BasePath('/foo'); + const basePath = new BasePath({ basePath: '/foo' }); const anonymousPaths = new AnonymousPathsService().setup({ basePath }); anonymousPaths.register('/BAR'); expect(anonymousPaths.isAnonymous('/foo/bar')).toBe(true); }); it('returns false for other paths', () => { - const basePath = new BasePath('/foo'); + const basePath = new BasePath({ basePath: '/foo' }); const anonymousPaths = new AnonymousPathsService().setup({ basePath }); anonymousPaths.register('/bar'); expect(anonymousPaths.isAnonymous('/foo/foo')).toBe(false); }); it('returns false for sub-paths of registered paths', () => { - const basePath = new BasePath('/foo'); + const basePath = new BasePath({ basePath: '/foo' }); const anonymousPaths = new AnonymousPathsService().setup({ basePath }); anonymousPaths.register('/bar'); expect(anonymousPaths.isAnonymous('/foo/bar/baz')).toBe(false); diff --git a/packages/core/http/core-http-browser-internal/src/base_path.test.ts b/packages/core/http/core-http-browser-internal/src/base_path.test.ts index cfca537c0f5b4..ebf70c48d79c3 100644 --- a/packages/core/http/core-http-browser-internal/src/base_path.test.ts +++ b/packages/core/http/core-http-browser-internal/src/base_path.test.ts @@ -10,35 +10,31 @@ import { BasePath } from './base_path'; describe('BasePath', () => { describe('#get()', () => { - it('returns an empty string if no basePath not provided', () => { - expect(new BasePath().get()).toBe(''); - }); - it('returns basePath value if provided', () => { - expect(new BasePath('/foo').get()).toBe('/foo'); + expect(new BasePath({ basePath: '/foo' }).get()).toBe('/foo'); }); describe('#prepend()', () => { it('adds the base path to the path if it is relative and starts with a slash', () => { - const basePath = new BasePath('/foo/bar'); + const basePath = new BasePath({ basePath: '/foo/bar' }); expect(basePath.prepend('/a/b')).toBe('/foo/bar/a/b'); }); it('leaves the query string and hash of path unchanged', () => { - const basePath = new BasePath('/foo/bar'); + const basePath = new BasePath({ basePath: '/foo/bar' }); expect(basePath.prepend('/a/b?x=y#c/d/e')).toBe('/foo/bar/a/b?x=y#c/d/e'); }); it('returns the path unchanged if it does not start with a slash', () => { - const basePath = new BasePath('/foo/bar'); + const basePath = new BasePath({ basePath: '/foo/bar' }); expect(basePath.prepend('a/b')).toBe('a/b'); }); it('returns the path unchanged it it has a hostname', () => { - const basePath = new BasePath('/foo/bar'); + const basePath = new BasePath({ basePath: '/foo/bar' }); expect(basePath.prepend('http://localhost:5601/a/b')).toBe('http://localhost:5601/a/b'); }); @@ -46,19 +42,19 @@ describe('BasePath', () => { describe('#remove()', () => { it('removes the basePath if relative path starts with it', () => { - const basePath = new BasePath('/foo/bar'); + const basePath = new BasePath({ basePath: '/foo/bar' }); expect(basePath.remove('/foo/bar/a/b')).toBe('/a/b'); }); it('leaves query string and hash intact', () => { - const basePath = new BasePath('/foo/bar'); + const basePath = new BasePath({ basePath: '/foo/bar' }); expect(basePath.remove('/foo/bar/a/b?c=y#1234')).toBe('/a/b?c=y#1234'); }); it('ignores urls with hostnames', () => { - const basePath = new BasePath('/foo/bar'); + const basePath = new BasePath({ basePath: '/foo/bar' }); expect(basePath.remove('http://localhost:5601/foo/bar/a/b')).toBe( 'http://localhost:5601/foo/bar/a/b' @@ -66,13 +62,13 @@ describe('BasePath', () => { }); it('returns slash if path is just basePath', () => { - const basePath = new BasePath('/foo/bar'); + const basePath = new BasePath({ basePath: '/foo/bar' }); expect(basePath.remove('/foo/bar')).toBe('/'); }); it('returns full path if basePath is not its own segment', () => { - const basePath = new BasePath('/foo/bar'); + const basePath = new BasePath({ basePath: '/foo/bar' }); expect(basePath.remove('/foo/barhop')).toBe('/foo/barhop'); }); @@ -81,20 +77,39 @@ describe('BasePath', () => { describe('serverBasePath', () => { it('defaults to basePath', () => { - expect(new BasePath('/foo/bar').serverBasePath).toEqual('/foo/bar'); + expect(new BasePath({ basePath: '/foo/bar' }).serverBasePath).toEqual('/foo/bar'); }); it('returns value when passed into constructor', () => { - expect(new BasePath('/foo/bar', '/foo').serverBasePath).toEqual('/foo'); + expect(new BasePath({ basePath: '/foo/bar', serverBasePath: '/foo' }).serverBasePath).toEqual( + '/foo' + ); }); }); describe('publicBaseUrl', () => { it('returns value passed into construtor', () => { - expect(new BasePath('/foo/bar', '/foo').publicBaseUrl).toEqual(undefined); - expect(new BasePath('/foo/bar', '/foo', 'http://myhost.com/foo').publicBaseUrl).toEqual( - 'http://myhost.com/foo' + expect(new BasePath({ basePath: '/foo/bar' }).publicBaseUrl).toEqual(undefined); + expect( + new BasePath({ basePath: '/foo/bar', publicBaseUrl: 'http://myhost.com/foo' }).publicBaseUrl + ).toEqual('http://myhost.com/foo'); + }); + }); + + describe('assetsHrefBase', () => { + it('default to the serverBasePath if unspecified', () => { + expect(new BasePath({ basePath: '/foo/bar', serverBasePath: '/foo' }).assetsHrefBase).toEqual( + '/foo' ); }); + it('returns the correct value when explicitly set', () => { + expect( + new BasePath({ + basePath: '/foo/bar', + serverBasePath: '/foo', + assetsHrefBase: 'http://cdn/foo', + }).assetsHrefBase + ).toEqual('http://cdn/foo'); + }); }); }); diff --git a/packages/core/http/core-http-browser-internal/src/base_path.ts b/packages/core/http/core-http-browser-internal/src/base_path.ts index 63fb8917421e0..4eaa71f8290d9 100644 --- a/packages/core/http/core-http-browser-internal/src/base_path.ts +++ b/packages/core/http/core-http-browser-internal/src/base_path.ts @@ -10,18 +10,36 @@ import { IBasePath } from '@kbn/core-http-browser'; import { modifyUrl } from '@kbn/std'; export class BasePath implements IBasePath { - constructor( - private readonly basePath: string = '', - public readonly serverBasePath: string = basePath, - public readonly publicBaseUrl?: string - ) {} + private readonly basePath: string; + public readonly serverBasePath: string; + public readonly assetsHrefBase: string; + public readonly publicBaseUrl?: string; + + constructor({ + basePath, + serverBasePath, + assetsHrefBase, + publicBaseUrl, + }: { + basePath: string; + serverBasePath?: string; + assetsHrefBase?: string; + publicBaseUrl?: string; + }) { + this.basePath = basePath; + this.serverBasePath = serverBasePath ?? this.basePath; + this.assetsHrefBase = assetsHrefBase ?? this.serverBasePath; + this.publicBaseUrl = publicBaseUrl; + } public get = () => { return this.basePath; }; public prepend = (path: string): string => { - if (!this.basePath) return path; + if (!this.basePath) { + return path; + } return modifyUrl(path, (parts) => { if (!parts.hostname && parts.pathname && parts.pathname.startsWith('/')) { parts.pathname = `${this.basePath}${parts.pathname}`; diff --git a/packages/core/http/core-http-browser-internal/src/fetch.test.ts b/packages/core/http/core-http-browser-internal/src/fetch.test.ts index b46a34f768b66..d4f37a6601b69 100644 --- a/packages/core/http/core-http-browser-internal/src/fetch.test.ts +++ b/packages/core/http/core-http-browser-internal/src/fetch.test.ts @@ -27,7 +27,7 @@ const BASE_PATH = 'http://localhost/myBase'; describe('Fetch', () => { const executionContextMock = executionContextServiceMock.createSetupContract(); const fetchInstance = new Fetch({ - basePath: new BasePath(BASE_PATH), + basePath: new BasePath({ basePath: BASE_PATH }), kibanaVersion: 'VERSION', buildNumber: 1234, executionContext: executionContextMock, diff --git a/packages/core/http/core-http-browser-internal/src/http_service.ts b/packages/core/http/core-http-browser-internal/src/http_service.ts index d097dc7a14c9a..a054ca3a7c11c 100644 --- a/packages/core/http/core-http-browser-internal/src/http_service.ts +++ b/packages/core/http/core-http-browser-internal/src/http_service.ts @@ -10,8 +10,9 @@ import type { CoreService } from '@kbn/core-base-browser-internal'; import type { ExecutionContextSetup } from '@kbn/core-execution-context-browser'; import type { InternalInjectedMetadataSetup } from '@kbn/core-injected-metadata-browser-internal'; import type { FatalErrorsSetup } from '@kbn/core-fatal-errors-browser'; -import type { HttpSetup, HttpStart } from '@kbn/core-http-browser'; +import type { InternalHttpSetup, InternalHttpStart } from './types'; import { BasePath } from './base_path'; +import { StaticAssets } from './static_assets'; import { AnonymousPathsService } from './anonymous_paths_service'; import { LoadingCountService } from './loading_count_service'; import { Fetch } from './fetch'; @@ -24,19 +25,23 @@ interface HttpDeps { } /** @internal */ -export class HttpService implements CoreService { +export class HttpService implements CoreService { private readonly anonymousPaths = new AnonymousPathsService(); private readonly loadingCount = new LoadingCountService(); - private service?: HttpSetup; + private service?: InternalHttpSetup; - public setup({ injectedMetadata, fatalErrors, executionContext }: HttpDeps): HttpSetup { + public setup({ injectedMetadata, fatalErrors, executionContext }: HttpDeps): InternalHttpSetup { const kibanaVersion = injectedMetadata.getKibanaVersion(); const buildNumber = injectedMetadata.getKibanaBuildNumber(); - const basePath = new BasePath( - injectedMetadata.getBasePath(), - injectedMetadata.getServerBasePath(), - injectedMetadata.getPublicBaseUrl() - ); + const basePath = new BasePath({ + basePath: injectedMetadata.getBasePath(), + serverBasePath: injectedMetadata.getServerBasePath(), + publicBaseUrl: injectedMetadata.getPublicBaseUrl(), + assetsHrefBase: injectedMetadata.getAssetsHrefBase(), + }); + const staticAssets = new StaticAssets({ + assetsHrefBase: injectedMetadata.getAssetsHrefBase(), + }); const fetchService = new Fetch({ basePath, kibanaVersion, buildNumber, executionContext }); const loadingCount = this.loadingCount.setup({ fatalErrors }); @@ -44,6 +49,7 @@ export class HttpService implements CoreService { this.service = { basePath, + staticAssets, anonymousPaths: this.anonymousPaths.setup({ basePath }), externalUrl: new ExternalUrlService().setup({ injectedMetadata, location: window.location }), intercept: fetchService.intercept.bind(fetchService), diff --git a/packages/core/http/core-http-browser-internal/src/static_assets.test.ts b/packages/core/http/core-http-browser-internal/src/static_assets.test.ts new file mode 100644 index 0000000000000..c9083e2fd0177 --- /dev/null +++ b/packages/core/http/core-http-browser-internal/src/static_assets.test.ts @@ -0,0 +1,34 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { StaticAssets } from './static_assets'; + +describe('StaticAssets', () => { + describe('#getPluginAssetHref()', () => { + it('returns the expected value when the base is a path', () => { + const staticAssets = new StaticAssets({ assetsHrefBase: '/base-path' }); + expect(staticAssets.getPluginAssetHref('foo', 'path/to/img.gif')).toEqual( + '/base-path/plugins/foo/assets/path/to/img.gif' + ); + }); + + it('returns the expected value when the base is a full url', () => { + const staticAssets = new StaticAssets({ assetsHrefBase: 'http://cdn/cdn-base-path' }); + expect(staticAssets.getPluginAssetHref('bar', 'path/to/img.gif')).toEqual( + 'http://cdn/cdn-base-path/plugins/bar/assets/path/to/img.gif' + ); + }); + + it('removes leading slash from the', () => { + const staticAssets = new StaticAssets({ assetsHrefBase: '/base-path' }); + expect(staticAssets.getPluginAssetHref('dolly', '/path/for/something.svg')).toEqual( + '/base-path/plugins/dolly/assets/path/for/something.svg' + ); + }); + }); +}); diff --git a/packages/core/http/core-http-browser-internal/src/static_assets.ts b/packages/core/http/core-http-browser-internal/src/static_assets.ts new file mode 100644 index 0000000000000..02218e3d375d6 --- /dev/null +++ b/packages/core/http/core-http-browser-internal/src/static_assets.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 { InternalStaticAssets } from './types'; + +export class StaticAssets implements InternalStaticAssets { + public readonly assetsHrefBase: string; + + constructor({ assetsHrefBase }: { assetsHrefBase: string }) { + this.assetsHrefBase = assetsHrefBase.endsWith('/') + ? assetsHrefBase.slice(0, -1) + : assetsHrefBase; + } + + getPluginAssetHref(pluginName: string, assetPath: string): string { + if (assetPath.startsWith('/')) { + assetPath = assetPath.slice(1); + } + return `${this.assetsHrefBase}/plugins/${pluginName}/assets/${assetPath}`; + } +} diff --git a/packages/core/http/core-http-browser-internal/src/types.ts b/packages/core/http/core-http-browser-internal/src/types.ts new file mode 100644 index 0000000000000..83e47ff0b7262 --- /dev/null +++ b/packages/core/http/core-http-browser-internal/src/types.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 and the Server Side Public License, v 1; you may 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 { HttpSetup, HttpStart } from '@kbn/core-http-browser'; + +export type InternalHttpSetup = Omit & { + staticAssets: InternalStaticAssets; +}; + +export type InternalHttpStart = Omit & { + staticAssets: InternalStaticAssets; +}; + +export interface InternalStaticAssets { + getPluginAssetHref(pluginId: string, assetPath: string): string; +} diff --git a/packages/core/http/core-http-browser-mocks/src/base_path.mock.ts b/packages/core/http/core-http-browser-mocks/src/base_path.mock.ts index 9d36d4e33c106..ad27677dd41ff 100644 --- a/packages/core/http/core-http-browser-mocks/src/base_path.mock.ts +++ b/packages/core/http/core-http-browser-mocks/src/base_path.mock.ts @@ -11,13 +11,15 @@ import type { IBasePath } from '@kbn/core-http-browser'; const createBasePathMock = ({ publicBaseUrl = '/', serverBasePath = '/', -}: { publicBaseUrl?: string; serverBasePath?: string } = {}) => { + assetsHrefBase = '/', +}: { publicBaseUrl?: string; serverBasePath?: string; assetsHrefBase?: string } = {}) => { const mock: jest.Mocked = { prepend: jest.fn(), get: jest.fn(), remove: jest.fn(), publicBaseUrl, serverBasePath, + assetsHrefBase, }; return mock; diff --git a/packages/core/http/core-http-browser-mocks/src/http_service.mock.ts b/packages/core/http/core-http-browser-mocks/src/http_service.mock.ts index 553e09875ae9e..45b445b39fad4 100644 --- a/packages/core/http/core-http-browser-mocks/src/http_service.mock.ts +++ b/packages/core/http/core-http-browser-mocks/src/http_service.mock.ts @@ -29,7 +29,10 @@ const createServiceMock = ({ patch: jest.fn(), delete: jest.fn(), options: jest.fn(), - basePath: new BasePath(basePath, undefined, publicBaseUrl), + basePath: new BasePath({ + basePath, + publicBaseUrl, + }), anonymousPaths: { register: jest.fn(), isAnonymous: jest.fn(), @@ -38,6 +41,9 @@ const createServiceMock = ({ isInternalUrl: jest.fn(), validateUrl: jest.fn(), }, + staticAssets: { + getPluginAssetHref: jest.fn(), + }, addLoadingCountSource: jest.fn(), getLoadingCount$: jest.fn().mockReturnValue(new BehaviorSubject(0)), intercept: jest.fn(), diff --git a/packages/core/http/core-http-browser/index.ts b/packages/core/http/core-http-browser/index.ts index 5f733d720c17d..de1e201132d3d 100644 --- a/packages/core/http/core-http-browser/index.ts +++ b/packages/core/http/core-http-browser/index.ts @@ -12,6 +12,7 @@ export type { IBasePath, IExternalUrl, IAnonymousPaths, + IStaticAssets, HttpHeadersInit, HttpRequestInit, HttpFetchQuery, diff --git a/packages/core/http/core-http-browser/src/types.ts b/packages/core/http/core-http-browser/src/types.ts index e9b3d2ecdd660..5d270d77afc2e 100644 --- a/packages/core/http/core-http-browser/src/types.ts +++ b/packages/core/http/core-http-browser/src/types.ts @@ -19,6 +19,12 @@ export interface HttpSetup { */ basePath: IBasePath; + /** + * APIs for creating hrefs to static assets. + * See {@link IStaticAssets} + */ + staticAssets: IStaticAssets; + /** * APIs for denoting certain paths for not requiring authentication */ @@ -96,6 +102,12 @@ export interface IBasePath { */ readonly serverBasePath: string; + /** + * Href (hypertext reference) intended to be used as the base for constructing + * other hrefs to static assets. + */ + readonly assetsHrefBase: string; + /** * The server's publicly exposed base URL, if configured. Includes protocol, host, port (optional) and the * {@link IBasePath.serverBasePath}. @@ -105,6 +117,7 @@ export interface IBasePath { */ readonly publicBaseUrl?: string; } + /** * APIs for working with external URLs. * @@ -130,6 +143,25 @@ export interface IExternalUrl { validateUrl(relativeOrAbsoluteUrl: string): URL | null; } +/** + * APIs for creating hrefs to static assets. + * + * @public + */ +export interface IStaticAssets { + /** + * Gets the full href to the current plugin's asset, + * given its path relative to the plugin's `public/assets` folder. + * + * @example + * ```ts + * // I want to retrieve the href for the asset stored under `my_plugin/public/assets/some_folder/asset.png`: + * const assetHref = core.http.statisAssets.getPluginAssetHref('some_folder/asset.png'); + * ``` + */ + getPluginAssetHref(assetPath: string): string; +} + /** * APIs for denoting paths as not requiring authentication */ @@ -318,10 +350,13 @@ export interface HttpHandler { path: string, options: HttpFetchOptions & { asResponse: true } ): Promise>; + (options: HttpFetchOptionsWithPath & { asResponse: true }): Promise< HttpResponse >; + (path: string, options?: HttpFetchOptions): Promise; + (options: HttpFetchOptionsWithPath): Promise; } @@ -368,6 +403,7 @@ export interface HttpInterceptorResponseError extends HttpResponse { request: Readonly; error: Error | IHttpFetchError; } + /** @public */ export interface HttpInterceptorRequestError { fetchOptions: Readonly; @@ -429,6 +465,7 @@ export interface HttpInterceptor { export interface IHttpInterceptController { /** Whether or not this chain has been halted. */ halted: boolean; + /** Halt the request Promise chain and do not process further interceptors or response handlers. */ halt(): void; } diff --git a/packages/core/http/core-http-server-internal/src/http_server.test.ts b/packages/core/http/core-http-server-internal/src/http_server.test.ts index f188d7a06552e..f70b035c5f22f 100644 --- a/packages/core/http/core-http-server-internal/src/http_server.test.ts +++ b/packages/core/http/core-http-server-internal/src/http_server.test.ts @@ -82,6 +82,7 @@ beforeEach(() => { cors: { enabled: false, }, + cdn: {}, shutdownTimeout: moment.duration(500, 'ms'), } as any; diff --git a/packages/core/http/core-http-server-internal/src/http_server.ts b/packages/core/http/core-http-server-internal/src/http_server.ts index c8a6f55e0a55e..fb776f5d29eb6 100644 --- a/packages/core/http/core-http-server-internal/src/http_server.ts +++ b/packages/core/http/core-http-server-internal/src/http_server.ts @@ -58,7 +58,7 @@ import { AuthStateStorage } from './auth_state_storage'; import { AuthHeadersStorage } from './auth_headers_storage'; import { BasePath } from './base_path_service'; import { getEcsResponseLog } from './logging'; -import { StaticAssets, type IStaticAssets } from './static_assets'; +import { StaticAssets, type InternalStaticAssets } from './static_assets'; /** * Adds ELU timings for the executed function to the current's context transaction @@ -136,7 +136,7 @@ export interface HttpServerSetup { * @note Static assets may be served over CDN */ registerStaticDir: (path: string, dirPath: string) => void; - staticAssets: IStaticAssets; + staticAssets: InternalStaticAssets; basePath: HttpServiceSetup['basePath']; csp: HttpServiceSetup['csp']; createCookieSessionStorageFactory: HttpServiceSetup['createCookieSessionStorageFactory']; diff --git a/packages/core/http/core-http-server-internal/src/http_service.ts b/packages/core/http/core-http-server-internal/src/http_service.ts index 96e9c8a85ba89..99d286b26f83f 100644 --- a/packages/core/http/core-http-server-internal/src/http_service.ts +++ b/packages/core/http/core-http-server-internal/src/http_service.ts @@ -199,7 +199,7 @@ export class HttpService // the `plugin` and `legacy` services. public getStartContract(): InternalHttpServiceStart { return { - ...pick(this.internalSetup!, ['auth', 'basePath', 'getServerInfo']), + ...pick(this.internalSetup!, ['auth', 'basePath', 'getServerInfo', 'staticAssets']), isListening: () => this.httpServer.isListening(), }; } diff --git a/packages/core/http/core-http-server-internal/src/static_assets.test.ts b/packages/core/http/core-http-server-internal/src/static_assets.test.ts index d80ec6aaf6ed8..0b1acd4e73fd9 100644 --- a/packages/core/http/core-http-server-internal/src/static_assets.test.ts +++ b/packages/core/http/core-http-server-internal/src/static_assets.test.ts @@ -14,18 +14,48 @@ describe('StaticAssets', () => { let basePath: BasePath; let cdnConfig: CdnConfig; let staticAssets: StaticAssets; + beforeEach(() => { - basePath = new BasePath('/test'); - cdnConfig = CdnConfig.from(); - staticAssets = new StaticAssets(basePath, cdnConfig); + basePath = new BasePath('/base-path'); }); - it('provides fallsback to server base path', () => { - expect(staticAssets.getHrefBase()).toEqual('/test'); + + describe('#getHrefBase()', () => { + it('provides fallback to server base path', () => { + cdnConfig = CdnConfig.from(); + staticAssets = new StaticAssets(basePath, cdnConfig); + expect(staticAssets.getHrefBase()).toEqual('/base-path'); + }); + + it('provides the correct HREF given a CDN is configured', () => { + cdnConfig = CdnConfig.from({ url: 'https://cdn.example.com/test' }); + staticAssets = new StaticAssets(basePath, cdnConfig); + expect(staticAssets.getHrefBase()).toEqual('https://cdn.example.com/test'); + }); }); - it('provides the correct HREF given a CDN is configured', () => { - cdnConfig = CdnConfig.from({ url: 'https://cdn.example.com/test' }); - staticAssets = new StaticAssets(basePath, cdnConfig); - expect(staticAssets.getHrefBase()).toEqual('https://cdn.example.com/test'); + describe('#getPluginAssetHref()', () => { + it('returns the expected value when CDN config is not set', () => { + cdnConfig = CdnConfig.from(); + staticAssets = new StaticAssets(basePath, cdnConfig); + expect(staticAssets.getPluginAssetHref('foo', 'path/to/img.gif')).toEqual( + '/base-path/plugins/foo/assets/path/to/img.gif' + ); + }); + + it('returns the expected value when CDN config is set', () => { + cdnConfig = CdnConfig.from({ url: 'https://cdn.example.com/test' }); + staticAssets = new StaticAssets(basePath, cdnConfig); + expect(staticAssets.getPluginAssetHref('bar', 'path/to/img.gif')).toEqual( + 'https://cdn.example.com/test/plugins/bar/assets/path/to/img.gif' + ); + }); + + it('removes leading slash from the', () => { + cdnConfig = CdnConfig.from(); + staticAssets = new StaticAssets(basePath, cdnConfig); + expect(staticAssets.getPluginAssetHref('dolly', '/path/for/something.svg')).toEqual( + '/base-path/plugins/dolly/assets/path/for/something.svg' + ); + }); }); }); diff --git a/packages/core/http/core-http-server-internal/src/static_assets.ts b/packages/core/http/core-http-server-internal/src/static_assets.ts index b4e7a529fe948..4dfe46d8d31a6 100644 --- a/packages/core/http/core-http-server-internal/src/static_assets.ts +++ b/packages/core/http/core-http-server-internal/src/static_assets.ts @@ -9,20 +9,31 @@ import type { BasePath } from './base_path_service'; import { CdnConfig } from './cdn'; -export interface IStaticAssets { +export interface InternalStaticAssets { getHrefBase(): string; + getPluginAssetHref(pluginName: string, assetPath: string): string; } -export class StaticAssets implements IStaticAssets { - constructor(private readonly basePath: BasePath, private readonly cdnConfig: CdnConfig) {} +export class StaticAssets implements InternalStaticAssets { + private readonly assetsHrefBase: string; + + constructor(basePath: BasePath, cdnConfig: CdnConfig) { + const hrefToUse = cdnConfig.baseHref ?? basePath.serverBasePath; + this.assetsHrefBase = hrefToUse.endsWith('/') ? hrefToUse.slice(0, -1) : hrefToUse; + } + /** * Returns a href (hypertext reference) intended to be used as the base for constructing * other hrefs to static assets. */ getHrefBase(): string { - if (this.cdnConfig.baseHref) { - return this.cdnConfig.baseHref; + return this.assetsHrefBase; + } + + getPluginAssetHref(pluginName: string, assetPath: string): string { + if (assetPath.startsWith('/')) { + assetPath = assetPath.slice(1); } - return this.basePath.serverBasePath; + return `${this.assetsHrefBase}/plugins/${pluginName}/assets/${assetPath}`; } } diff --git a/packages/core/http/core-http-server-internal/src/types.ts b/packages/core/http/core-http-server-internal/src/types.ts index 0acbb0d0508d6..72dde630e03db 100644 --- a/packages/core/http/core-http-server-internal/src/types.ts +++ b/packages/core/http/core-http-server-internal/src/types.ts @@ -16,8 +16,9 @@ import type { HttpServiceSetup, HttpServiceStart, } from '@kbn/core-http-server'; -import { HttpServerSetup } from './http_server'; -import { ExternalUrlConfig } from './external_url'; +import type { HttpServerSetup } from './http_server'; +import type { ExternalUrlConfig } from './external_url'; +import type { InternalStaticAssets } from './static_assets'; /** @internal */ export interface InternalHttpServicePreboot @@ -43,10 +44,10 @@ export interface InternalHttpServicePreboot /** @internal */ export interface InternalHttpServiceSetup - extends Omit { + extends Omit { auth: HttpServerSetup['auth']; server: HttpServerSetup['server']; - staticAssets: HttpServerSetup['staticAssets']; + staticAssets: InternalStaticAssets; externalUrl: ExternalUrlConfig; createRouter: ( path: string, @@ -66,7 +67,8 @@ export interface InternalHttpServiceSetup } /** @internal */ -export interface InternalHttpServiceStart extends HttpServiceStart { +export interface InternalHttpServiceStart extends Omit { + staticAssets: InternalStaticAssets; /** Indicates if the http server is listening on the configured port */ isListening: () => boolean; } diff --git a/packages/core/http/core-http-server-mocks/src/http_service.mock.ts b/packages/core/http/core-http-server-mocks/src/http_service.mock.ts index ad7e310f5a2d8..f8ecfadfeb87e 100644 --- a/packages/core/http/core-http-server-mocks/src/http_service.mock.ts +++ b/packages/core/http/core-http-server-mocks/src/http_service.mock.ts @@ -20,6 +20,7 @@ import type { HttpServicePreboot, HttpServiceSetup, HttpServiceStart, + IStaticAssets, } from '@kbn/core-http-server'; import { AuthStatus } from '@kbn/core-http-server'; import { mockRouter, RouterMock } from '@kbn/core-http-router-server-mocks'; @@ -34,17 +35,19 @@ import type { import { sessionStorageMock } from './cookie_session_storage.mocks'; type BasePathMocked = jest.Mocked; -type StaticAssetsMocked = jest.Mocked; +type InternalStaticAssetsMocked = jest.Mocked; +type StaticAssetsMocked = jest.Mocked; type AuthMocked = jest.Mocked; export type HttpServicePrebootMock = jest.Mocked; export type InternalHttpServicePrebootMock = jest.Mocked< Omit -> & { basePath: BasePathMocked; staticAssets: StaticAssetsMocked }; +> & { basePath: BasePathMocked; staticAssets: InternalStaticAssetsMocked }; export type HttpServiceSetupMock< ContextType extends RequestHandlerContextBase = RequestHandlerContextBase > = jest.Mocked, 'basePath' | 'createRouter'>> & { basePath: BasePathMocked; + staticAssets: StaticAssetsMocked; createRouter: jest.MockedFunction<() => RouterMock>; }; export type InternalHttpServiceSetupMock = jest.Mocked< @@ -55,15 +58,17 @@ export type InternalHttpServiceSetupMock = jest.Mocked< > & { auth: AuthMocked; basePath: BasePathMocked; - staticAssets: StaticAssetsMocked; + staticAssets: InternalStaticAssetsMocked; createRouter: jest.MockedFunction<(path: string) => RouterMock>; authRequestHeaders: jest.Mocked; }; export type HttpServiceStartMock = jest.Mocked & { basePath: BasePathMocked; + staticAssets: StaticAssetsMocked; }; export type InternalHttpServiceStartMock = jest.Mocked & { basePath: BasePathMocked; + staticAssets: InternalStaticAssetsMocked; }; const createBasePathMock = ( @@ -78,11 +83,12 @@ const createBasePathMock = ( remove: jest.fn(), }); -const createStaticAssetsMock = ( +const createInternalStaticAssetsMock = ( basePath: BasePathMocked, cdnUrl: undefined | string = undefined -): StaticAssetsMocked => ({ +): InternalStaticAssetsMocked => ({ getHrefBase: jest.fn(() => cdnUrl ?? basePath.serverBasePath), + getPluginAssetHref: jest.fn().mockReturnValue(cdnUrl ?? basePath.serverBasePath), }); const createAuthMock = () => { @@ -106,6 +112,7 @@ const createAuthHeaderStorageMock = () => { interface CreateMockArgs { cdnUrl?: string; } + const createInternalPrebootContractMock = (args: CreateMockArgs = {}) => { const basePath = createBasePathMock(); const mock: InternalHttpServicePrebootMock = { @@ -113,7 +120,7 @@ const createInternalPrebootContractMock = (args: CreateMockArgs = {}) => { registerRouteHandlerContext: jest.fn(), registerStaticDir: jest.fn(), basePath, - staticAssets: createStaticAssetsMock(basePath, args.cdnUrl), + staticAssets: createInternalStaticAssetsMock(basePath, args.cdnUrl), csp: CspConfig.DEFAULT, externalUrl: ExternalUrlConfig.DEFAULT, auth: createAuthMock(), @@ -144,6 +151,7 @@ const createPrebootContractMock = () => { }; const createInternalSetupContractMock = () => { + const basePath = createBasePathMock(); const mock: InternalHttpServiceSetupMock = { // we can mock other hapi server methods when we need it server: { @@ -164,9 +172,9 @@ const createInternalSetupContractMock = () => { registerOnPreResponse: jest.fn(), createRouter: jest.fn().mockImplementation(() => mockRouter.create({})), registerStaticDir: jest.fn(), - basePath: createBasePathMock(), + basePath, csp: CspConfig.DEFAULT, - staticAssets: { getHrefBase: jest.fn(() => mock.basePath.serverBasePath) }, + staticAssets: createInternalStaticAssetsMock(basePath), externalUrl: ExternalUrlConfig.DEFAULT, auth: createAuthMock(), authRequestHeaders: createAuthHeaderStorageMock(), @@ -202,6 +210,9 @@ const createSetupContractMock = < createRouter: jest.fn(), registerRouteHandlerContext: jest.fn(), getServerInfo: internalMock.getServerInfo, + staticAssets: { + getPluginAssetHref: jest.fn().mockImplementation((assetPath: string) => assetPath), + }, }; mock.createRouter.mockImplementation(() => internalMock.createRouter('')); @@ -214,14 +225,19 @@ const createStartContractMock = () => { auth: createAuthMock(), basePath: createBasePathMock(), getServerInfo: jest.fn(), + staticAssets: { + getPluginAssetHref: jest.fn().mockImplementation((assetPath: string) => assetPath), + }, }; return mock; }; const createInternalStartContractMock = () => { + const basePath = createBasePathMock(); const mock: InternalHttpServiceStartMock = { ...createStartContractMock(), + staticAssets: createInternalStaticAssetsMock(basePath), isListening: jest.fn(), }; diff --git a/packages/core/http/core-http-server/index.ts b/packages/core/http/core-http-server/index.ts index 94eefba610a44..9a28a7be5033e 100644 --- a/packages/core/http/core-http-server/index.ts +++ b/packages/core/http/core-http-server/index.ts @@ -142,3 +142,5 @@ export type { VersionedRouteRegistrar, VersionedRouter, } from './src/versioning'; + +export type { IStaticAssets } from './src/static_assets'; diff --git a/packages/core/http/core-http-server/src/http_contract.ts b/packages/core/http/core-http-server/src/http_contract.ts index 753b7b8cf0066..8ac34b26a386c 100644 --- a/packages/core/http/core-http-server/src/http_contract.ts +++ b/packages/core/http/core-http-server/src/http_contract.ts @@ -20,6 +20,7 @@ import type { OnPreRoutingHandler, } from './lifecycle'; import type { IBasePath } from './base_path'; +import type { IStaticAssets } from './static_assets'; import type { ICspConfig } from './csp'; import type { GetAuthState, IsAuthenticated } from './auth_state'; import type { SessionStorageCookieOptions, SessionStorageFactory } from './session_storage'; @@ -287,6 +288,12 @@ export interface HttpServiceSetup< */ basePath: IBasePath; + /** + * APIs for creating hrefs to static assets. + * See {@link IStaticAssets} + */ + staticAssets: IStaticAssets; + /** * The CSP config used for Kibana. */ @@ -361,6 +368,12 @@ export interface HttpServiceStart { */ basePath: IBasePath; + /** + * APIs for creating hrefs to static assets. + * See {@link IStaticAssets} + */ + staticAssets: IStaticAssets; + /** * Auth status. * See {@link HttpAuth} diff --git a/packages/core/http/core-http-server/src/static_assets.ts b/packages/core/http/core-http-server/src/static_assets.ts new file mode 100644 index 0000000000000..c0cc8597d1540 --- /dev/null +++ b/packages/core/http/core-http-server/src/static_assets.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. + */ + +/** + * APIs for creating hrefs to static assets. + * + * @public + */ +export interface IStaticAssets { + /** + * Gets the full href to the current plugin's asset, + * given its path relative to the plugin's `public/assets` folder. + * + * @example + * ```ts + * // I want to retrieve the href for the asset stored under `my_plugin/public/assets/some_folder/asset.png`: + * const assetHref = core.http.statisAssets.getPluginAssetHref('some_folder/asset.png'); + * ``` + */ + getPluginAssetHref(assetPath: string): string; +} diff --git a/packages/core/injected-metadata/core-injected-metadata-browser-internal/src/injected_metadata_service.ts b/packages/core/injected-metadata/core-injected-metadata-browser-internal/src/injected_metadata_service.ts index ca818f9f79dc7..a50de7ca3f5e7 100644 --- a/packages/core/injected-metadata/core-injected-metadata-browser-internal/src/injected_metadata_service.ts +++ b/packages/core/injected-metadata/core-injected-metadata-browser-internal/src/injected_metadata_service.ts @@ -48,6 +48,10 @@ export class InjectedMetadataService { return this.state.publicBaseUrl; }, + getAssetsHrefBase: () => { + return this.state.assetsHrefBase; + }, + getAnonymousStatusPage: () => { return this.state.anonymousStatusPage; }, diff --git a/packages/core/injected-metadata/core-injected-metadata-browser-internal/src/types.ts b/packages/core/injected-metadata/core-injected-metadata-browser-internal/src/types.ts index 67c9c6ff4d665..3b996e68e50b3 100644 --- a/packages/core/injected-metadata/core-injected-metadata-browser-internal/src/types.ts +++ b/packages/core/injected-metadata/core-injected-metadata-browser-internal/src/types.ts @@ -29,6 +29,7 @@ export interface InternalInjectedMetadataSetup { getBasePath: () => string; getServerBasePath: () => string; getPublicBaseUrl: () => string | undefined; + getAssetsHrefBase: () => string; getKibanaBuildNumber: () => number; getKibanaBranch: () => string; getKibanaVersion: () => string; diff --git a/packages/core/injected-metadata/core-injected-metadata-browser-mocks/src/injected_metadata_service.mock.ts b/packages/core/injected-metadata/core-injected-metadata-browser-mocks/src/injected_metadata_service.mock.ts index 98f1f8c65c37f..3d76d48cbdb9b 100644 --- a/packages/core/injected-metadata/core-injected-metadata-browser-mocks/src/injected_metadata_service.mock.ts +++ b/packages/core/injected-metadata/core-injected-metadata-browser-mocks/src/injected_metadata_service.mock.ts @@ -16,6 +16,7 @@ const createSetupContractMock = () => { const setupContract: jest.Mocked = { getBasePath: jest.fn(), getServerBasePath: jest.fn(), + getAssetsHrefBase: jest.fn(), getPublicBaseUrl: jest.fn(), getKibanaVersion: jest.fn(), getKibanaBranch: jest.fn(), @@ -31,6 +32,9 @@ const createSetupContractMock = () => { getKibanaBuildNumber: jest.fn(), getCustomBranding: jest.fn(), }; + setupContract.getBasePath.mockReturnValue('/base-path'); + setupContract.getServerBasePath.mockReturnValue('/server-base-path'); + setupContract.getAssetsHrefBase.mockReturnValue('/assets-base-path'); setupContract.getCspConfig.mockReturnValue({ warnLegacyBrowsers: true }); setupContract.getExternalUrlConfig.mockReturnValue({ policy: [] }); setupContract.getKibanaVersion.mockReturnValue('kibanaVersion'); diff --git a/packages/core/injected-metadata/core-injected-metadata-common-internal/src/types.ts b/packages/core/injected-metadata/core-injected-metadata-common-internal/src/types.ts index 944ec94554b25..dd9d6bced5c98 100644 --- a/packages/core/injected-metadata/core-injected-metadata-common-internal/src/types.ts +++ b/packages/core/injected-metadata/core-injected-metadata-common-internal/src/types.ts @@ -42,6 +42,7 @@ export interface InjectedMetadata { basePath: string; serverBasePath: string; publicBaseUrl?: string; + assetsHrefBase: string; clusterInfo: InjectedMetadataClusterInfo; env: { mode: EnvironmentMode; diff --git a/packages/core/lifecycle/core-lifecycle-browser-internal/src/internal_core_setup.ts b/packages/core/lifecycle/core-lifecycle-browser-internal/src/internal_core_setup.ts index 9ef51b986458c..396c834082422 100644 --- a/packages/core/lifecycle/core-lifecycle-browser-internal/src/internal_core_setup.ts +++ b/packages/core/lifecycle/core-lifecycle-browser-internal/src/internal_core_setup.ts @@ -9,10 +9,12 @@ import type { CoreSetup } from '@kbn/core-lifecycle-browser'; import type { InternalApplicationSetup } from '@kbn/core-application-browser-internal'; import type { InternalInjectedMetadataSetup } from '@kbn/core-injected-metadata-browser-internal'; +import type { InternalHttpSetup } from '@kbn/core-http-browser-internal'; /** @internal */ export interface InternalCoreSetup - extends Omit { + extends Omit { application: InternalApplicationSetup; injectedMetadata: InternalInjectedMetadataSetup; + http: InternalHttpSetup; } diff --git a/packages/core/lifecycle/core-lifecycle-browser-internal/src/internal_core_start.ts b/packages/core/lifecycle/core-lifecycle-browser-internal/src/internal_core_start.ts index f6b20626cd561..1806f52b8292d 100644 --- a/packages/core/lifecycle/core-lifecycle-browser-internal/src/internal_core_start.ts +++ b/packages/core/lifecycle/core-lifecycle-browser-internal/src/internal_core_start.ts @@ -9,9 +9,11 @@ import type { CoreStart } from '@kbn/core-lifecycle-browser'; import type { InternalApplicationStart } from '@kbn/core-application-browser-internal'; import type { InternalInjectedMetadataStart } from '@kbn/core-injected-metadata-browser-internal'; +import type { InternalHttpStart } from '@kbn/core-http-browser-internal'; /** @internal */ -export interface InternalCoreStart extends Omit { +export interface InternalCoreStart extends Omit { application: InternalApplicationStart; injectedMetadata: InternalInjectedMetadataStart; + http: InternalHttpStart; } diff --git a/packages/core/lifecycle/core-lifecycle-browser-internal/tsconfig.json b/packages/core/lifecycle/core-lifecycle-browser-internal/tsconfig.json index 5f6dcff8fd678..7d5c7fd5c06fd 100644 --- a/packages/core/lifecycle/core-lifecycle-browser-internal/tsconfig.json +++ b/packages/core/lifecycle/core-lifecycle-browser-internal/tsconfig.json @@ -14,7 +14,8 @@ "kbn_references": [ "@kbn/core-lifecycle-browser", "@kbn/core-application-browser-internal", - "@kbn/core-injected-metadata-browser-internal" + "@kbn/core-injected-metadata-browser-internal", + "@kbn/core-http-browser-internal" ], "exclude": [ "target/**/*", diff --git a/packages/core/logging/core-logging-server-internal/src/layouts/json_layout.test.ts b/packages/core/logging/core-logging-server-internal/src/layouts/json_layout.test.ts index dfa2144c28015..60b415b1b2a2b 100644 --- a/packages/core/logging/core-logging-server-internal/src/layouts/json_layout.test.ts +++ b/packages/core/logging/core-logging-server-internal/src/layouts/json_layout.test.ts @@ -365,3 +365,90 @@ test('format() meta can not override tracing properties', () => { transaction: { id: 'transaction_override' }, }); }); + +test('format() meta.toJSON() is used if own property', () => { + const layout = new JsonLayout(); + expect( + JSON.parse( + layout.format({ + message: 'foo', + timestamp, + level: LogLevel.Debug, + context: 'bar', + pid: 3, + meta: { + server: { + address: 'localhost', + }, + service: { + version: '1', + }, + // @ts-expect-error cannot override @timestamp + toJSON() { + return { + server: { + address: 'localhost', + }, + }; + }, + }, + }) + ) + ).toStrictEqual({ + ecs: { version: expect.any(String) }, + '@timestamp': '2012-02-01T09:30:22.011-05:00', + message: 'foo', + log: { + level: 'DEBUG', + logger: 'bar', + }, + process: { + pid: 3, + }, + server: { + address: 'localhost', + }, + }); +}); + +test('format() meta.toJSON() is used if present on prototype', () => { + class SomeClass { + foo: string = 'bar'; + hello: string = 'dolly'; + + toJSON() { + return { + foo: this.foo, + }; + } + } + + const someInstance = new SomeClass(); + + const layout = new JsonLayout(); + expect( + JSON.parse( + layout.format({ + message: 'foo', + timestamp, + level: LogLevel.Debug, + context: 'bar', + pid: 3, + // @ts-expect-error meta is not of the correct type + meta: someInstance, + }) + ) + ).toStrictEqual({ + ecs: { version: expect.any(String) }, + '@timestamp': '2012-02-01T09:30:22.011-05:00', + message: 'foo', + log: { + level: 'DEBUG', + logger: 'bar', + }, + process: { + pid: 3, + }, + foo: 'bar', + }); +}); diff --git a/packages/core/logging/core-logging-server-internal/src/layouts/json_layout.ts b/packages/core/logging/core-logging-server-internal/src/layouts/json_layout.ts index cd41b7675464e..43b906fa8407c 100644 --- a/packages/core/logging/core-logging-server-internal/src/layouts/json_layout.ts +++ b/packages/core/logging/core-logging-server-internal/src/layouts/json_layout.ts @@ -58,7 +58,13 @@ export class JsonLayout implements Layout { trace: traceId ? { id: traceId } : undefined, transaction: transactionId ? { id: transactionId } : undefined, }; - const output = record.meta ? merge({ ...record.meta }, log) : log; + + let output = log; + if (record.meta) { + // @ts-expect-error toJSON not defined on `LogMeta`, but some structured meta can have it defined + const serializedMeta = record.meta.toJSON ? record.meta.toJSON() : { ...record.meta }; + output = merge(serializedMeta, log); + } return JSON.stringify(output); } diff --git a/packages/core/plugins/core-plugins-browser-internal/src/plugin_context.ts b/packages/core/plugins/core-plugins-browser-internal/src/plugin_context.ts index 604eb86093758..94ada11ac5b24 100644 --- a/packages/core/plugins/core-plugins-browser-internal/src/plugin_context.ts +++ b/packages/core/plugins/core-plugins-browser-internal/src/plugin_context.ts @@ -82,7 +82,13 @@ export function createPluginSetupContext< customBranding: deps.customBranding, fatalErrors: deps.fatalErrors, executionContext: deps.executionContext, - http: deps.http, + http: { + ...deps.http, + staticAssets: { + getPluginAssetHref: (assetPath: string) => + deps.http.staticAssets.getPluginAssetHref(plugin.name, assetPath), + }, + }, notifications: deps.notifications, uiSettings: deps.uiSettings, settings: deps.settings, @@ -133,7 +139,13 @@ export function createPluginStartContext< customBranding: deps.customBranding, docLinks: deps.docLinks, executionContext: deps.executionContext, - http: deps.http, + http: { + ...deps.http, + staticAssets: { + getPluginAssetHref: (assetPath: string) => + deps.http.staticAssets.getPluginAssetHref(plugin.name, assetPath), + }, + }, chrome: omit(deps.chrome, 'getComponent'), i18n: deps.i18n, notifications: deps.notifications, diff --git a/packages/core/plugins/core-plugins-browser-internal/src/plugins_service.test.ts b/packages/core/plugins/core-plugins-browser-internal/src/plugins_service.test.ts index 00c056a20d87d..c1c612d387204 100644 --- a/packages/core/plugins/core-plugins-browser-internal/src/plugins_service.test.ts +++ b/packages/core/plugins/core-plugins-browser-internal/src/plugins_service.test.ts @@ -104,6 +104,10 @@ describe('PluginsService', () => { application: expect.any(Object), plugins: expect.any(Object), getStartServices: expect.any(Function), + http: { + ...mockSetupDeps.http, + staticAssets: expect.any(Object), + }, }; // @ts-expect-error this file was not being type checked properly in the past, error is legit mockStartDeps = { @@ -128,6 +132,10 @@ describe('PluginsService', () => { application: expect.any(Object), plugins: expect.any(Object), chrome: omit(mockStartDeps.chrome, 'getComponent'), + http: { + ...mockStartDeps.http, + staticAssets: expect.any(Object), + }, }; // Reset these for each test. diff --git a/packages/core/plugins/core-plugins-server-internal/src/plugin.test.ts b/packages/core/plugins/core-plugins-server-internal/src/plugin.test.ts index 5b11139397a12..128c674753129 100644 --- a/packages/core/plugins/core-plugins-server-internal/src/plugin.test.ts +++ b/packages/core/plugins/core-plugins-server-internal/src/plugin.test.ts @@ -157,7 +157,7 @@ describe('`constructor` correctly sets non-external source', () => { }); }); -test('`setup` fails if `plugin` initializer is not exported', () => { +test('`setup` fails if the plugin has not been initialized', () => { const manifest = createPluginManifest(); const opaqueId = Symbol(); const plugin = new PluginWrapper({ @@ -176,11 +176,32 @@ test('`setup` fails if `plugin` initializer is not exported', () => { expect(() => plugin.setup(createPluginSetupContext({ deps: setupDeps, plugin, runtimeResolver }), {}) ).toThrowErrorMatchingInlineSnapshot( + `"The plugin is not initialized. Call the init method first."` + ); +}); + +test('`init` fails if `plugin` initializer is not exported', async () => { + const manifest = createPluginManifest(); + const opaqueId = Symbol(); + const plugin = new PluginWrapper({ + path: 'plugin-without-initializer-path', + manifest, + opaqueId, + initializerContext: createPluginInitializerContext({ + coreContext, + opaqueId, + manifest, + instanceInfo, + nodeInfo, + }), + }); + + await expect(() => plugin.init()).rejects.toThrowErrorMatchingInlineSnapshot( `"Plugin \\"some-plugin-id\\" does not export \\"plugin\\" definition (plugin-without-initializer-path)."` ); }); -test('`setup` fails if plugin initializer is not a function', () => { +test('`init` fails if plugin initializer is not a function', async () => { const manifest = createPluginManifest(); const opaqueId = Symbol(); const plugin = new PluginWrapper({ @@ -196,14 +217,12 @@ test('`setup` fails if plugin initializer is not a function', () => { }), }); - expect(() => - plugin.setup(createPluginSetupContext({ deps: setupDeps, plugin, runtimeResolver }), {}) - ).toThrowErrorMatchingInlineSnapshot( + await expect(() => plugin.init()).rejects.toThrowErrorMatchingInlineSnapshot( `"Definition of plugin \\"some-plugin-id\\" should be a function (plugin-with-wrong-initializer-path)."` ); }); -test('`setup` fails if initializer does not return object', () => { +test('`init` fails if initializer does not return object', async () => { const manifest = createPluginManifest(); const opaqueId = Symbol(); const plugin = new PluginWrapper({ @@ -219,16 +238,14 @@ test('`setup` fails if initializer does not return object', () => { }), }); - mockPluginInitializer.mockReturnValue(null); + mockPluginInitializer.mockResolvedValue(null); - expect(() => - plugin.setup(createPluginSetupContext({ deps: setupDeps, plugin, runtimeResolver }), {}) - ).toThrowErrorMatchingInlineSnapshot( + await expect(() => plugin.init()).rejects.toThrowErrorMatchingInlineSnapshot( `"Initializer for plugin \\"some-plugin-id\\" is expected to return plugin instance, but returned \\"null\\"."` ); }); -test('`setup` fails if object returned from initializer does not define `setup` function', () => { +test('`init` fails if object returned from initializer does not define `setup` function', async () => { const manifest = createPluginManifest(); const opaqueId = Symbol(); const plugin = new PluginWrapper({ @@ -245,11 +262,9 @@ test('`setup` fails if object returned from initializer does not define `setup` }); const mockPluginInstance = { run: jest.fn() }; - mockPluginInitializer.mockReturnValue(mockPluginInstance); + mockPluginInitializer.mockResolvedValue(mockPluginInstance); - expect(() => - plugin.setup(createPluginSetupContext({ deps: setupDeps, plugin, runtimeResolver }), {}) - ).toThrowErrorMatchingInlineSnapshot( + await expect(() => plugin.init()).rejects.toThrowErrorMatchingInlineSnapshot( `"Instance of plugin \\"some-plugin-id\\" does not define \\"setup\\" function."` ); }); @@ -272,7 +287,9 @@ test('`setup` initializes plugin and calls appropriate lifecycle hook', async () }); const mockPluginInstance = { setup: jest.fn().mockResolvedValue({ contract: 'yes' }) }; - mockPluginInitializer.mockReturnValue(mockPluginInstance); + mockPluginInitializer.mockResolvedValue(mockPluginInstance); + + await plugin.init(); const setupContext = createPluginSetupContext({ deps: setupDeps, plugin, runtimeResolver }); const setupDependencies = { 'some-required-dep': { contract: 'no' } }; @@ -323,8 +340,9 @@ test('`start` fails invoked for the `preboot` plugin', async () => { }); const mockPluginInstance = { setup: jest.fn() }; - mockPluginInitializer.mockReturnValue(mockPluginInstance); + mockPluginInitializer.mockResolvedValue(mockPluginInstance); + await plugin.init(); await plugin.setup({} as any, {} as any); expect(() => plugin.start({} as any, {} as any)).toThrowErrorMatchingInlineSnapshot( @@ -355,8 +373,9 @@ test('`start` calls plugin.start with context and dependencies', async () => { setup: jest.fn(), start: jest.fn().mockResolvedValue(pluginStartContract), }; - mockPluginInitializer.mockReturnValue(mockPluginInstance); + mockPluginInitializer.mockResolvedValue(mockPluginInstance); + await plugin.init(); await plugin.setup({} as any, {} as any); const startContract = await plugin.start(context, deps); @@ -399,8 +418,9 @@ test("`start` resolves `startDependencies` Promise after plugin's start", async return pluginStartContract; }, }; - mockPluginInitializer.mockReturnValue(mockPluginInstance); + mockPluginInitializer.mockResolvedValue(mockPluginInstance); + await plugin.init(); await plugin.setup({} as any, {} as any); const startDependenciesCheck = plugin.startDependencies.then((resolvedStartDeps) => { @@ -429,7 +449,7 @@ test('`stop` fails if plugin is not set up', async () => { }); const mockPluginInstance = { setup: jest.fn(), stop: jest.fn() }; - mockPluginInitializer.mockReturnValue(mockPluginInstance); + mockPluginInitializer.mockResolvedValue(mockPluginInstance); await expect(plugin.stop()).rejects.toMatchInlineSnapshot( `[Error: Plugin "some-plugin-id" can't be stopped since it isn't set up.]` @@ -453,7 +473,8 @@ test('`stop` does nothing if plugin does not define `stop` function', async () = }), }); - mockPluginInitializer.mockReturnValue({ setup: jest.fn() }); + mockPluginInitializer.mockResolvedValue({ setup: jest.fn() }); + await plugin.init(); await plugin.setup(createPluginSetupContext({ deps: setupDeps, plugin, runtimeResolver }), {}); await expect(plugin.stop()).resolves.toBeUndefined(); @@ -476,7 +497,8 @@ test('`stop` calls `stop` defined by the plugin instance', async () => { }); const mockPluginInstance = { setup: jest.fn(), stop: jest.fn() }; - mockPluginInitializer.mockReturnValue(mockPluginInstance); + mockPluginInitializer.mockResolvedValue(mockPluginInstance); + await plugin.init(); await plugin.setup(createPluginSetupContext({ deps: setupDeps, plugin, runtimeResolver }), {}); await expect(plugin.stop()).resolves.toBeUndefined(); diff --git a/packages/core/plugins/core-plugins-server-internal/src/plugin.ts b/packages/core/plugins/core-plugins-server-internal/src/plugin.ts index 3a8015aad4d59..7877886198cf5 100644 --- a/packages/core/plugins/core-plugins-server-internal/src/plugin.ts +++ b/packages/core/plugins/core-plugins-server-internal/src/plugin.ts @@ -87,6 +87,10 @@ export class PluginWrapper< this.includesUiPlugin = params.manifest.ui; } + public async init() { + this.instance = await this.createPluginInstance(); + } + /** * Instantiates plugin and calls `setup` function exposed by the plugin initializer. * @param setupContext Context that consists of various core services tailored specifically @@ -98,7 +102,9 @@ export class PluginWrapper< setupContext: CoreSetup | CorePreboot, plugins: TPluginsSetup ): TSetup | Promise { - this.instance = this.createPluginInstance(); + if (!this.instance) { + throw new Error('The plugin is not initialized. Call the init method first.'); + } if (this.isPrebootPluginInstance(this.instance)) { return this.instance.setup(setupContext as CorePreboot, plugins); @@ -170,7 +176,7 @@ export class PluginWrapper< return configDescriptor; } - private createPluginInstance() { + private async createPluginInstance() { this.log.debug('Initializing plugin'); // eslint-disable-next-line @typescript-eslint/no-var-requires @@ -186,7 +192,7 @@ export class PluginWrapper< throw new Error(`Definition of plugin "${this.name}" should be a function (${this.path}).`); } - const instance = initializer(this.initializerContext); + const instance = await initializer(this.initializerContext); if (!instance || typeof instance !== 'object') { throw new Error( `Initializer for plugin "${ diff --git a/packages/core/plugins/core-plugins-server-internal/src/plugin_context.ts b/packages/core/plugins/core-plugins-server-internal/src/plugin_context.ts index 8d493e78aae8b..c3ed7f6a433b9 100644 --- a/packages/core/plugins/core-plugins-server-internal/src/plugin_context.ts +++ b/packages/core/plugins/core-plugins-server-internal/src/plugin_context.ts @@ -235,6 +235,10 @@ export function createPluginSetupContext({ registerOnPostAuth: deps.http.registerOnPostAuth, registerOnPreResponse: deps.http.registerOnPreResponse, basePath: deps.http.basePath, + staticAssets: { + getPluginAssetHref: (assetPath: string) => + deps.http.staticAssets.getPluginAssetHref(plugin.name, assetPath), + }, csp: deps.http.csp, getServerInfo: deps.http.getServerInfo, }, @@ -324,6 +328,10 @@ export function createPluginStartContext({ auth: deps.http.auth, basePath: deps.http.basePath, getServerInfo: deps.http.getServerInfo, + staticAssets: { + getPluginAssetHref: (assetPath: string) => + deps.http.staticAssets.getPluginAssetHref(plugin.name, assetPath), + }, }, savedObjects: { getScopedClient: deps.savedObjects.getScopedClient, diff --git a/packages/core/plugins/core-plugins-server-internal/src/plugins_service.ts b/packages/core/plugins/core-plugins-server-internal/src/plugins_service.ts index bfa6b6ab5a222..03327b1d7be52 100644 --- a/packages/core/plugins/core-plugins-server-internal/src/plugins_service.ts +++ b/packages/core/plugins/core-plugins-server-internal/src/plugins_service.ts @@ -201,7 +201,7 @@ export class PluginsService this.log.debug('Stopping plugins service'); if (!this.arePrebootPluginsStopped) { - this.arePrebootPluginsStopped = false; + this.arePrebootPluginsStopped = true; await this.prebootPluginsSystem.stopPlugins(); } diff --git a/packages/core/plugins/core-plugins-server-internal/src/plugins_system.test.ts b/packages/core/plugins/core-plugins-server-internal/src/plugins_system.test.ts index 42ea7012745f2..5406b60cb09e8 100644 --- a/packages/core/plugins/core-plugins-server-internal/src/plugins_system.test.ts +++ b/packages/core/plugins/core-plugins-server-internal/src/plugins_system.test.ts @@ -43,7 +43,7 @@ function createPlugin( type?: PluginType; } = {} ): PluginWrapper { - return new PluginWrapper({ + const plugin = new PluginWrapper({ path: 'some-path', manifest: { id, @@ -62,6 +62,8 @@ function createPlugin( opaqueId: Symbol(id), initializerContext: { logger } as any, }); + jest.spyOn(plugin, 'init').mockResolvedValue(); + return plugin; } const prebootDeps = coreInternalLifecycleMock.createInternalPreboot(); @@ -602,7 +604,10 @@ describe('setup', () => { mockCreatePluginSetupContext.mockImplementation(() => ({})); const promise = pluginsSystem.setupPlugins(setupDeps); - jest.runAllTimers(); + process.nextTick(() => { + // let the await init go through. then simulate the timeout + jest.runAllTimers(); + }); await expect(promise).rejects.toMatchInlineSnapshot( `[Error: Setup lifecycle of "timeout-setup" plugin wasn't completed in 10sec. Consider disabling the plugin and re-start.]` diff --git a/packages/core/plugins/core-plugins-server-internal/src/plugins_system.ts b/packages/core/plugins/core-plugins-server-internal/src/plugins_system.ts index a7ca6d64da545..6b5d14846b754 100644 --- a/packages/core/plugins/core-plugins-server-internal/src/plugins_system.ts +++ b/packages/core/plugins/core-plugins-server-internal/src/plugins_system.ts @@ -131,6 +131,7 @@ export class PluginsSystem { }); } + await plugin.init(); let contract: unknown; const contractOrPromise = plugin.setup(pluginSetupContext, pluginDepContracts); if (isPromise(contractOrPromise)) { diff --git a/packages/core/plugins/core-plugins-server/src/types.ts b/packages/core/plugins/core-plugins-server/src/types.ts index e518bd7db7eb6..297bdb147c292 100644 --- a/packages/core/plugins/core-plugins-server/src/types.ts +++ b/packages/core/plugins/core-plugins-server/src/types.ts @@ -473,7 +473,8 @@ export type PluginInitializer< TPluginsStart extends object = object > = ( core: PluginInitializerContext -) => +) => Promise< | Plugin | PrebootPlugin - | AsyncPlugin; + | AsyncPlugin +>; diff --git a/packages/core/rendering/core-rendering-server-internal/src/__snapshots__/rendering_service.test.ts.snap b/packages/core/rendering/core-rendering-server-internal/src/__snapshots__/rendering_service.test.ts.snap index d444959de3c9e..535624e4a8320 100644 --- a/packages/core/rendering/core-rendering-server-internal/src/__snapshots__/rendering_service.test.ts.snap +++ b/packages/core/rendering/core-rendering-server-internal/src/__snapshots__/rendering_service.test.ts.snap @@ -3,6 +3,7 @@ exports[`RenderingService preboot() render() renders "core" CDN url injected 1`] = ` Object { "anonymousStatusPage": false, + "assetsHrefBase": "http://foo.bar:1773", "basePath": "/mock-server-basepath", "branch": Any, "buildNumber": Any, @@ -70,6 +71,7 @@ Object { exports[`RenderingService preboot() render() renders "core" page 1`] = ` Object { "anonymousStatusPage": false, + "assetsHrefBase": "/mock-server-basepath", "basePath": "/mock-server-basepath", "branch": Any, "buildNumber": Any, @@ -133,6 +135,7 @@ Object { exports[`RenderingService preboot() render() renders "core" page driven by settings 1`] = ` Object { "anonymousStatusPage": false, + "assetsHrefBase": "/mock-server-basepath", "basePath": "/mock-server-basepath", "branch": Any, "buildNumber": Any, @@ -200,6 +203,7 @@ Object { exports[`RenderingService preboot() render() renders "core" page for blank basepath 1`] = ` Object { "anonymousStatusPage": false, + "assetsHrefBase": "/mock-server-basepath", "basePath": "", "branch": Any, "buildNumber": Any, @@ -263,6 +267,7 @@ Object { exports[`RenderingService preboot() render() renders "core" page for unauthenticated requests 1`] = ` Object { "anonymousStatusPage": false, + "assetsHrefBase": "/mock-server-basepath", "basePath": "/mock-server-basepath", "branch": Any, "buildNumber": Any, @@ -326,6 +331,7 @@ Object { exports[`RenderingService preboot() render() renders "core" page with global settings 1`] = ` Object { "anonymousStatusPage": false, + "assetsHrefBase": "/mock-server-basepath", "basePath": "/mock-server-basepath", "branch": Any, "buildNumber": Any, @@ -393,6 +399,7 @@ Object { exports[`RenderingService preboot() render() renders "core" with excluded global user settings 1`] = ` Object { "anonymousStatusPage": false, + "assetsHrefBase": "/mock-server-basepath", "basePath": "/mock-server-basepath", "branch": Any, "buildNumber": Any, @@ -456,6 +463,7 @@ Object { exports[`RenderingService preboot() render() renders "core" with excluded user settings 1`] = ` Object { "anonymousStatusPage": false, + "assetsHrefBase": "/mock-server-basepath", "basePath": "/mock-server-basepath", "branch": Any, "buildNumber": Any, @@ -519,6 +527,7 @@ Object { exports[`RenderingService setup() render() renders "core" CDN url injected 1`] = ` Object { "anonymousStatusPage": false, + "assetsHrefBase": "/mock-server-basepath", "basePath": "/mock-server-basepath", "branch": Any, "buildNumber": Any, @@ -591,6 +600,7 @@ Object { exports[`RenderingService setup() render() renders "core" page 1`] = ` Object { "anonymousStatusPage": false, + "assetsHrefBase": "/mock-server-basepath", "basePath": "/mock-server-basepath", "branch": Any, "buildNumber": Any, @@ -654,6 +664,7 @@ Object { exports[`RenderingService setup() render() renders "core" page driven by settings 1`] = ` Object { "anonymousStatusPage": false, + "assetsHrefBase": "/mock-server-basepath", "basePath": "/mock-server-basepath", "branch": Any, "buildNumber": Any, @@ -726,6 +737,7 @@ Object { exports[`RenderingService setup() render() renders "core" page for blank basepath 1`] = ` Object { "anonymousStatusPage": false, + "assetsHrefBase": "/mock-server-basepath", "basePath": "", "branch": Any, "buildNumber": Any, @@ -794,6 +806,7 @@ Object { exports[`RenderingService setup() render() renders "core" page for unauthenticated requests 1`] = ` Object { "anonymousStatusPage": false, + "assetsHrefBase": "/mock-server-basepath", "basePath": "/mock-server-basepath", "branch": Any, "buildNumber": Any, @@ -857,6 +870,7 @@ Object { exports[`RenderingService setup() render() renders "core" page with global settings 1`] = ` Object { "anonymousStatusPage": false, + "assetsHrefBase": "/mock-server-basepath", "basePath": "/mock-server-basepath", "branch": Any, "buildNumber": Any, @@ -929,6 +943,7 @@ Object { exports[`RenderingService setup() render() renders "core" with excluded global user settings 1`] = ` Object { "anonymousStatusPage": false, + "assetsHrefBase": "/mock-server-basepath", "basePath": "/mock-server-basepath", "branch": Any, "buildNumber": Any, @@ -997,6 +1012,7 @@ Object { exports[`RenderingService setup() render() renders "core" with excluded user settings 1`] = ` Object { "anonymousStatusPage": false, + "assetsHrefBase": "/mock-server-basepath", "basePath": "/mock-server-basepath", "branch": Any, "buildNumber": Any, diff --git a/packages/core/rendering/core-rendering-server-internal/src/rendering_service.tsx b/packages/core/rendering/core-rendering-server-internal/src/rendering_service.tsx index 1791f55e563b6..f5bb1f5fa115f 100644 --- a/packages/core/rendering/core-rendering-server-internal/src/rendering_service.tsx +++ b/packages/core/rendering/core-rendering-server-internal/src/rendering_service.tsx @@ -209,6 +209,7 @@ export class RenderingService { basePath, serverBasePath, publicBaseUrl, + assetsHrefBase: staticAssetsHrefBase, env, clusterInfo, anonymousStatusPage: status?.isStatusPageAnonymous() ?? false, diff --git a/packages/core/saved-objects/core-saved-objects-browser-internal/src/saved_objects_client.ts b/packages/core/saved-objects/core-saved-objects-browser-internal/src/saved_objects_client.ts index 0493652b1192f..a5e112ca2aa74 100644 --- a/packages/core/saved-objects/core-saved-objects-browser-internal/src/saved_objects_client.ts +++ b/packages/core/saved-objects/core-saved-objects-browser-internal/src/saved_objects_client.ts @@ -7,7 +7,8 @@ */ import { pick, throttle, cloneDeep } from 'lodash'; -import type { HttpSetup, HttpFetchOptions } from '@kbn/core-http-browser'; +import type { HttpFetchOptions } from '@kbn/core-http-browser'; +import type { InternalHttpSetup } from '@kbn/core-http-browser-internal'; import type { SavedObject, SavedObjectTypeIdTuple } from '@kbn/core-saved-objects-common'; import type { SavedObjectsBulkResolveResponse as SavedObjectsBulkResolveResponseServer, @@ -106,7 +107,7 @@ const getObjectsToResolve = (queue: BatchResolveQueueEntry[]) => { * @deprecated See https://github.com/elastic/kibana/issues/149098 */ export class SavedObjectsClient implements SavedObjectsClientContract { - private http: HttpSetup; + private http: InternalHttpSetup; private batchGetQueue: BatchGetQueueEntry[]; private batchResolveQueue: BatchResolveQueueEntry[]; @@ -180,7 +181,7 @@ export class SavedObjectsClient implements SavedObjectsClientContract { ); /** @internal */ - constructor(http: HttpSetup) { + constructor(http: InternalHttpSetup) { this.http = http; this.batchGetQueue = []; this.batchResolveQueue = []; diff --git a/packages/core/saved-objects/core-saved-objects-browser-internal/src/saved_objects_service.ts b/packages/core/saved-objects/core-saved-objects-browser-internal/src/saved_objects_service.ts index 7cef8a1c39057..f806dc6b69ef0 100644 --- a/packages/core/saved-objects/core-saved-objects-browser-internal/src/saved_objects_service.ts +++ b/packages/core/saved-objects/core-saved-objects-browser-internal/src/saved_objects_service.ts @@ -7,7 +7,7 @@ */ import type { CoreService } from '@kbn/core-base-browser-internal'; -import type { HttpStart } from '@kbn/core-http-browser'; +import type { InternalHttpStart } from '@kbn/core-http-browser-internal'; import type { SavedObjectsStart } from '@kbn/core-saved-objects-browser'; import { SavedObjectsClient } from './saved_objects_client'; @@ -17,7 +17,7 @@ import { SavedObjectsClient } from './saved_objects_client'; export class SavedObjectsService implements CoreService { public async setup() {} - public async start({ http }: { http: HttpStart }): Promise { + public async start({ http }: { http: InternalHttpStart }): Promise { return { client: new SavedObjectsClient(http) }; } diff --git a/packages/core/saved-objects/core-saved-objects-browser-internal/tsconfig.json b/packages/core/saved-objects/core-saved-objects-browser-internal/tsconfig.json index a29dbf58b4117..d9b414c39220e 100644 --- a/packages/core/saved-objects/core-saved-objects-browser-internal/tsconfig.json +++ b/packages/core/saved-objects/core-saved-objects-browser-internal/tsconfig.json @@ -19,6 +19,7 @@ "@kbn/core-saved-objects-api-server", "@kbn/core-saved-objects-api-browser", "@kbn/core-http-browser-mocks", + "@kbn/core-http-browser-internal", ], "exclude": [ "target/**/*", diff --git a/packages/core/ui-settings/core-ui-settings-browser-internal/src/__snapshots__/ui_settings_api.test.ts.snap b/packages/core/ui-settings/core-ui-settings-browser-internal/src/__snapshots__/ui_settings_api.test.ts.snap index b80765e3536c9..eb5eb00c04ee3 100644 --- a/packages/core/ui-settings/core-ui-settings-browser-internal/src/__snapshots__/ui_settings_api.test.ts.snap +++ b/packages/core/ui-settings/core-ui-settings-browser-internal/src/__snapshots__/ui_settings_api.test.ts.snap @@ -253,3 +253,26 @@ Array [ ], ] `; + +exports[`#validate rejects on 301 1`] = `"Moved Permanently"`; + +exports[`#validate rejects on 404 response 1`] = `"Request failed with status code: 404"`; + +exports[`#validate rejects on 500 1`] = `"Request failed with status code: 500"`; + +exports[`#validate sends a validation request: validation request 1`] = ` +Array [ + Array [ + "/foo/bar/internal/kibana/settings/foo/validate", + Object { + "headers": Object { + "accept": "application/json", + "content-type": "application/json", + "kbn-version": "kibanaVersion", + "x-elastic-internal-origin": "Kibana", + }, + "method": "POST", + }, + ], +] +`; diff --git a/packages/core/ui-settings/core-ui-settings-browser-internal/src/settings_service.ts b/packages/core/ui-settings/core-ui-settings-browser-internal/src/settings_service.ts index edda603644fa2..202f8ceb1206d 100644 --- a/packages/core/ui-settings/core-ui-settings-browser-internal/src/settings_service.ts +++ b/packages/core/ui-settings/core-ui-settings-browser-internal/src/settings_service.ts @@ -9,14 +9,14 @@ import { Subject } from 'rxjs'; import type { InternalInjectedMetadataSetup } from '@kbn/core-injected-metadata-browser-internal'; -import type { HttpSetup } from '@kbn/core-http-browser'; +import type { InternalHttpSetup } from '@kbn/core-http-browser-internal'; import type { SettingsStart, SettingsSetup } from '@kbn/core-ui-settings-browser'; import { UiSettingsApi } from './ui_settings_api'; import { UiSettingsClient } from './ui_settings_client'; import { UiSettingsGlobalClient } from './ui_settings_global_client'; export interface SettingsServiceDeps { - http: HttpSetup; + http: InternalHttpSetup; injectedMetadata: InternalInjectedMetadataSetup; } diff --git a/packages/core/ui-settings/core-ui-settings-browser-internal/src/ui_settings_api.test.ts b/packages/core/ui-settings/core-ui-settings-browser-internal/src/ui_settings_api.test.ts index 9fbbb4045583a..992e2230988de 100644 --- a/packages/core/ui-settings/core-ui-settings-browser-internal/src/ui_settings_api.test.ts +++ b/packages/core/ui-settings/core-ui-settings-browser-internal/src/ui_settings_api.test.ts @@ -345,3 +345,45 @@ describe('#stop', () => { await batchSetPromise; }); }); + +describe('#validate', () => { + it('sends a validation request', async () => { + fetchMock.mock('*', { + body: { errorMessage: 'Test validation error message.' }, + }); + + const { uiSettingsApi } = setup(); + await uiSettingsApi.validate('foo', 'bar'); + expect(fetchMock.calls()).toMatchSnapshot('validation request'); + }); + + it('rejects on 404 response', async () => { + fetchMock.mock('*', { + status: 404, + body: 'not found', + }); + + const { uiSettingsApi } = setup(); + await expect(uiSettingsApi.validate('foo', 'bar')).rejects.toThrowErrorMatchingSnapshot(); + }); + + it('rejects on 301', async () => { + fetchMock.mock('*', { + status: 301, + body: 'redirect', + }); + + const { uiSettingsApi } = setup(); + await expect(uiSettingsApi.validate('foo', 'bar')).rejects.toThrowErrorMatchingSnapshot(); + }); + + it('rejects on 500', async () => { + fetchMock.mock('*', { + status: 500, + body: 'redirect', + }); + + const { uiSettingsApi } = setup(); + await expect(uiSettingsApi.validate('foo', 'bar')).rejects.toThrowErrorMatchingSnapshot(); + }); +}); diff --git a/packages/core/ui-settings/core-ui-settings-browser-internal/src/ui_settings_api.ts b/packages/core/ui-settings/core-ui-settings-browser-internal/src/ui_settings_api.ts index c96232b9f9b48..c26d2369d4e08 100644 --- a/packages/core/ui-settings/core-ui-settings-browser-internal/src/ui_settings_api.ts +++ b/packages/core/ui-settings/core-ui-settings-browser-internal/src/ui_settings_api.ts @@ -7,7 +7,7 @@ */ import { BehaviorSubject } from 'rxjs'; -import type { HttpSetup } from '@kbn/core-http-browser'; +import type { InternalHttpSetup } from '@kbn/core-http-browser-internal'; import type { UiSettingsState } from '@kbn/core-ui-settings-browser'; import { UiSettingsScope } from '@kbn/core-ui-settings-common'; @@ -16,6 +16,11 @@ export interface UiSettingsApiResponse { settings: UiSettingsState; } +export interface ValidationApiResponse { + valid: boolean; + errorMessage?: string; +} + interface Changes { values: { [key: string]: any; @@ -37,7 +42,7 @@ export class UiSettingsApi { private readonly loadingCount$ = new BehaviorSubject(0); - constructor(private readonly http: HttpSetup) {} + constructor(private readonly http: InternalHttpSetup) {} /** * Adds a key+value that will be sent to the server ASAP. If a request is @@ -94,6 +99,15 @@ export class UiSettingsApi { }); } + /** + * Sends a validation request to the server for the provided key+value pair. + */ + public async validate(key: string, value: any): Promise { + return await this.sendRequest('POST', `/internal/kibana/settings/${key}/validate`, { + value, + }); + } + /** * Gets an observable that notifies subscribers of the current number of active requests */ diff --git a/packages/core/ui-settings/core-ui-settings-browser-internal/src/ui_settings_client.test.ts b/packages/core/ui-settings/core-ui-settings-browser-internal/src/ui_settings_client.test.ts index 8e8a4af6aa00c..58da98f91e105 100644 --- a/packages/core/ui-settings/core-ui-settings-browser-internal/src/ui_settings_client.test.ts +++ b/packages/core/ui-settings/core-ui-settings-browser-internal/src/ui_settings_client.test.ts @@ -10,6 +10,9 @@ import { Subject } from 'rxjs'; import { materialize, take, toArray } from 'rxjs/operators'; import { UiSettingsClient } from './ui_settings_client'; +import { ValidationApiResponse } from './ui_settings_api'; + +const TEST_VALIDATION_ERROR_MESSAGE = 'Test validation message.'; let done$: Subject; @@ -22,6 +25,12 @@ function setup(options: { defaults?: any; initialSettings?: any } = {}) { const batchSetGlobal = jest.fn(() => ({ settings: {}, })); + const validate = jest.fn( + (): ValidationApiResponse => ({ + valid: false, + errorMessage: TEST_VALIDATION_ERROR_MESSAGE, + }) + ); done$ = new Subject(); const client = new UiSettingsClient({ defaults, @@ -29,11 +38,12 @@ function setup(options: { defaults?: any; initialSettings?: any } = {}) { api: { batchSet, batchSetGlobal, + validate, } as any, done$, }); - return { client, batchSet, batchSetGlobal }; + return { client, batchSet, batchSetGlobal, validate }; } afterEach(() => { @@ -283,3 +293,27 @@ describe('#getUpdate$', () => { expect(onComplete).toHaveBeenCalled(); }); }); + +describe('#validateValue', () => { + it('resolves to a ValueValidation', async () => { + const { client } = setup(); + + await expect(client.validateValue('foo', 'bar')).resolves.toMatchObject({ + successfulValidation: true, + valid: false, + errorMessage: TEST_VALIDATION_ERROR_MESSAGE, + }); + }); + + it('resolves to a ValueValidation on failure', async () => { + const { client, validate } = setup(); + + validate.mockImplementation(() => { + throw new Error('Error in request'); + }); + + await expect(client.validateValue('foo', 'bar')).resolves.toMatchObject({ + successfulValidation: false, + }); + }); +}); diff --git a/packages/core/ui-settings/core-ui-settings-browser-internal/src/ui_settings_client_common.ts b/packages/core/ui-settings/core-ui-settings-browser-internal/src/ui_settings_client_common.ts index 65a3c44861ed5..cccb0f85bb0d7 100644 --- a/packages/core/ui-settings/core-ui-settings-browser-internal/src/ui_settings_client_common.ts +++ b/packages/core/ui-settings/core-ui-settings-browser-internal/src/ui_settings_client_common.ts @@ -128,6 +128,19 @@ You can use \`IUiSettingsClient.get("${key}", defaultValue)\`, which will just r return this.updateErrors$.asObservable(); } + async validateValue(key: string, value: unknown) { + try { + const resp = await this.api.validate(key, value); + const isValid = resp.valid; + return isValid + ? { successfulValidation: true, valid: true } + : { successfulValidation: true, valid: false, errorMessage: resp.errorMessage }; + } catch (error) { + this.updateErrors$.next(error); + return { successfulValidation: false }; + } + } + protected assertUpdateAllowed(key: string) { if (this.isOverridden(key)) { throw new Error( diff --git a/packages/core/ui-settings/core-ui-settings-browser-internal/src/ui_settings_service.ts b/packages/core/ui-settings/core-ui-settings-browser-internal/src/ui_settings_service.ts index c531d18aded13..5827919f21ad5 100644 --- a/packages/core/ui-settings/core-ui-settings-browser-internal/src/ui_settings_service.ts +++ b/packages/core/ui-settings/core-ui-settings-browser-internal/src/ui_settings_service.ts @@ -9,14 +9,14 @@ import { Subject } from 'rxjs'; import type { InternalInjectedMetadataSetup } from '@kbn/core-injected-metadata-browser-internal'; -import type { HttpSetup } from '@kbn/core-http-browser'; +import type { InternalHttpSetup } from '@kbn/core-http-browser-internal'; import type { IUiSettingsClient } from '@kbn/core-ui-settings-browser'; import { UiSettingsApi } from './ui_settings_api'; import { UiSettingsClient } from './ui_settings_client'; export interface UiSettingsServiceDeps { - http: HttpSetup; + http: InternalHttpSetup; injectedMetadata: InternalInjectedMetadataSetup; } diff --git a/packages/core/ui-settings/core-ui-settings-browser-internal/tsconfig.json b/packages/core/ui-settings/core-ui-settings-browser-internal/tsconfig.json index 0beed2d6ddfb0..bcedc9db9175e 100644 --- a/packages/core/ui-settings/core-ui-settings-browser-internal/tsconfig.json +++ b/packages/core/ui-settings/core-ui-settings-browser-internal/tsconfig.json @@ -12,12 +12,12 @@ ], "kbn_references": [ "@kbn/core-test-helpers-http-setup-browser", - "@kbn/core-http-browser", "@kbn/core-ui-settings-browser", "@kbn/core-ui-settings-common", "@kbn/core-http-browser-mocks", "@kbn/core-injected-metadata-browser-mocks", "@kbn/core-injected-metadata-browser-internal", + "@kbn/core-http-browser-internal", ], "exclude": [ "target/**/*", diff --git a/packages/core/ui-settings/core-ui-settings-browser-mocks/src/client.mock.ts b/packages/core/ui-settings/core-ui-settings-browser-mocks/src/client.mock.ts index 0f7c9a6bd0ad5..93ca7d065b0fd 100644 --- a/packages/core/ui-settings/core-ui-settings-browser-mocks/src/client.mock.ts +++ b/packages/core/ui-settings/core-ui-settings-browser-mocks/src/client.mock.ts @@ -22,6 +22,7 @@ export const clientMock = () => { isOverridden: jest.fn(), getUpdate$: jest.fn(), getUpdateErrors$: jest.fn(), + validateValue: jest.fn(), }; mock.get$.mockReturnValue(new Subject()); mock.getUpdate$.mockReturnValue(new Subject()); diff --git a/packages/core/ui-settings/core-ui-settings-browser/src/types.ts b/packages/core/ui-settings/core-ui-settings-browser/src/types.ts index 1227df2309265..6927506a5338b 100644 --- a/packages/core/ui-settings/core-ui-settings-browser/src/types.ts +++ b/packages/core/ui-settings/core-ui-settings-browser/src/types.ts @@ -16,6 +16,12 @@ export interface UiSettingsState { [key: string]: PublicUiSettingsParams & UserProvidedValues; } +export interface ValueValidation { + successfulValidation: boolean; + valid?: boolean; + errorMessage?: string; +} + /** * Client-side client that provides access to the advanced settings stored in elasticsearch. * The settings provide control over the behavior of the Kibana application. @@ -100,6 +106,11 @@ export interface IUiSettingsClient { * the settings, containing the actual Error class. */ getUpdateErrors$: () => Observable; + + /** + * Validates a uiSettings value and returns a ValueValidation object. + */ + validateValue: (key: string, value: any) => Promise; } /** @public */ diff --git a/packages/core/ui-settings/core-ui-settings-server-internal/src/clients/base_ui_settings_client.ts b/packages/core/ui-settings/core-ui-settings-server-internal/src/clients/base_ui_settings_client.ts index 2d6e2d93a4313..90205f8afa643 100644 --- a/packages/core/ui-settings/core-ui-settings-server-internal/src/clients/base_ui_settings_client.ts +++ b/packages/core/ui-settings/core-ui-settings-server-internal/src/clients/base_ui_settings_client.ts @@ -10,6 +10,7 @@ import { omit } from 'lodash'; import type { Logger } from '@kbn/logging'; import type { UiSettingsParams, UserProvidedValues } from '@kbn/core-ui-settings-common'; import type { IUiSettingsClient } from '@kbn/core-ui-settings-server'; +import { ValidationBadValueError, ValidationSettingNotFoundError } from '../ui_settings_errors'; export interface BaseUiSettingsDefaultsClientOptions { overrides?: Record; @@ -72,6 +73,24 @@ export abstract class BaseUiSettingsClient implements IUiSettingsClient { return !!definition?.sensitive; } + async validate(key: string, value: unknown) { + if (!value) { + throw new ValidationBadValueError(); + } + const definition = this.defaults[key]; + if (!definition) { + throw new ValidationSettingNotFoundError(key); + } + if (definition.schema) { + try { + definition.schema.validate(value); + } catch (error) { + return { valid: false, errorMessage: error.message }; + } + } + return { valid: true }; + } + protected validateKey(key: string, value: unknown) { const definition = this.defaults[key]; if (value === null || definition === undefined) return; diff --git a/packages/core/ui-settings/core-ui-settings-server-internal/src/clients/ui_settings_client.test.ts b/packages/core/ui-settings/core-ui-settings-server-internal/src/clients/ui_settings_client.test.ts index b00517d259a48..7baa7afad9b25 100644 --- a/packages/core/ui-settings/core-ui-settings-server-internal/src/clients/ui_settings_client.test.ts +++ b/packages/core/ui-settings/core-ui-settings-server-internal/src/clients/ui_settings_client.test.ts @@ -13,7 +13,11 @@ import { mockCreateOrUpgradeSavedConfig } from './ui_settings_client.test.mock'; import { SavedObjectsClient } from '@kbn/core-saved-objects-api-server-internal'; import { savedObjectsClientMock } from '@kbn/core-saved-objects-api-server-mocks'; import { UiSettingsClient } from './ui_settings_client'; -import { CannotOverrideError } from '../ui_settings_errors'; +import { + CannotOverrideError, + ValidationBadValueError, + ValidationSettingNotFoundError, +} from '../ui_settings_errors'; const logger = loggingSystemMock.create().get(); @@ -732,6 +736,48 @@ describe('ui settings', () => { }); }); + describe('#validate()', () => { + it('returns a correct validation response for an existing setting key and an invalid value', async () => { + const defaults = { foo: { schema: schema.number() } }; + const { uiSettings } = setup({ defaults }); + + expect(await uiSettings.validate('foo', 'testValue')).toMatchObject({ + valid: false, + errorMessage: 'expected value of type [number] but got [string]', + }); + }); + + it('returns a correct validation response for an existing setting key and a valid value', async () => { + const defaults = { foo: { schema: schema.number() } }; + const { uiSettings } = setup({ defaults }); + + expect(await uiSettings.validate('foo', 5)).toMatchObject({ valid: true }); + }); + + it('throws for a non-existing setting key', async () => { + const { uiSettings } = setup(); + + try { + await uiSettings.validate('bar', 5); + } catch (error) { + expect(error).toBeInstanceOf(ValidationSettingNotFoundError); + expect(error.message).toBe('Setting with a key [bar] does not exist.'); + } + }); + + it('throws for a null value', async () => { + const defaults = { foo: { schema: schema.number() } }; + const { uiSettings } = setup({ defaults }); + + try { + await uiSettings.validate('foo', null); + } catch (error) { + expect(error).toBeInstanceOf(ValidationBadValueError); + expect(error.message).toBe('No value was specified.'); + } + }); + }); + describe('caching', () => { describe('read operations cache user config', () => { beforeEach(() => { diff --git a/packages/core/ui-settings/core-ui-settings-server-internal/src/routes/internal/index.ts b/packages/core/ui-settings/core-ui-settings-server-internal/src/routes/internal/index.ts index e15ded76ab6b8..dccadb6c02f68 100644 --- a/packages/core/ui-settings/core-ui-settings-server-internal/src/routes/internal/index.ts +++ b/packages/core/ui-settings/core-ui-settings-server-internal/src/routes/internal/index.ts @@ -11,10 +11,12 @@ import { registerInternalDeleteRoute } from './delete'; import { registerInternalGetRoute } from './get'; import { registerInternalSetManyRoute } from './set_many'; import { registerInternalSetRoute } from './set'; +import { registerInternalValidateRoute } from './validate'; export function registerInternalRoutes(router: InternalUiSettingsRouter) { registerInternalGetRoute(router); registerInternalDeleteRoute(router); registerInternalSetRoute(router); registerInternalSetManyRoute(router); + registerInternalValidateRoute(router); } diff --git a/packages/core/ui-settings/core-ui-settings-server-internal/src/routes/internal/validate.ts b/packages/core/ui-settings/core-ui-settings-server-internal/src/routes/internal/validate.ts new file mode 100644 index 0000000000000..83f119c658a85 --- /dev/null +++ b/packages/core/ui-settings/core-ui-settings-server-internal/src/routes/internal/validate.ts @@ -0,0 +1,72 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { schema } from '@kbn/config-schema'; +import { KibanaRequest, KibanaResponseFactory } from '@kbn/core-http-server'; +import { IUiSettingsClient } from '@kbn/core-ui-settings-server'; +import { ValidationBadValueError, ValidationSettingNotFoundError } from '../../ui_settings_errors'; +import type { + InternalUiSettingsRequestHandlerContext, + InternalUiSettingsRouter, +} from '../../internal_types'; + +export function registerInternalValidateRoute(router: InternalUiSettingsRouter) { + const validateFromRequest = async ( + uiSettingsClient: IUiSettingsClient, + context: InternalUiSettingsRequestHandlerContext, + request: KibanaRequest< + Readonly<{} & { key: string }>, + unknown, + Readonly<{ value?: any } & {}>, + 'post' + >, + response: KibanaResponseFactory + ) => { + try { + const { key } = request.params; + const { value } = request.body; + + const { valid, errorMessage } = await uiSettingsClient.validate(key, value); + + return response.ok({ + body: { + valid, + errorMessage, + }, + }); + } catch (error) { + if (error instanceof ValidationSettingNotFoundError) { + return response.notFound({ body: error }); + } + + if (error instanceof ValidationBadValueError) { + return response.badRequest({ body: error }); + } + + throw error; + } + }; + router.post( + { + path: '/internal/kibana/settings/{key}/validate', + validate: { + params: schema.object({ + key: schema.string(), + }), + body: schema.object({ + value: schema.any(), + }), + }, + options: { access: 'internal' }, + }, + async (context, request, response) => { + const uiSettingsClient = (await context.core).uiSettings.client; + return await validateFromRequest(uiSettingsClient, context, request, response); + } + ); +} diff --git a/packages/core/ui-settings/core-ui-settings-server-internal/src/ui_settings_errors.ts b/packages/core/ui-settings/core-ui-settings-server-internal/src/ui_settings_errors.ts index 755ed6447c5ed..93cec94bc71ad 100644 --- a/packages/core/ui-settings/core-ui-settings-server-internal/src/ui_settings_errors.ts +++ b/packages/core/ui-settings/core-ui-settings-server-internal/src/ui_settings_errors.ts @@ -27,3 +27,15 @@ export class SettingNotRegisteredError extends Error { ); } } + +export class ValidationSettingNotFoundError extends Error { + constructor(key: string) { + super(`Setting with a key [${key}] does not exist.`); + } +} + +export class ValidationBadValueError extends Error { + constructor() { + super('No value was specified.'); + } +} diff --git a/packages/core/ui-settings/core-ui-settings-server-mocks/src/ui_settings_service.mock.ts b/packages/core/ui-settings/core-ui-settings-server-mocks/src/ui_settings_service.mock.ts index 280d75319a8bf..7149da0d517b6 100644 --- a/packages/core/ui-settings/core-ui-settings-server-mocks/src/ui_settings_service.mock.ts +++ b/packages/core/ui-settings/core-ui-settings-server-mocks/src/ui_settings_service.mock.ts @@ -27,6 +27,7 @@ const createClientMock = () => { removeMany: jest.fn(), isOverridden: jest.fn(), isSensitive: jest.fn(), + validate: jest.fn(), }; mocked.get.mockResolvedValue(false); mocked.getAll.mockResolvedValue({}); diff --git a/packages/core/ui-settings/core-ui-settings-server/src/ui_settings_client.ts b/packages/core/ui-settings/core-ui-settings-server/src/ui_settings_client.ts index 9a297109002de..d4b16ae6ffe1c 100644 --- a/packages/core/ui-settings/core-ui-settings-server/src/ui_settings_client.ts +++ b/packages/core/ui-settings/core-ui-settings-server/src/ui_settings_client.ts @@ -8,6 +8,11 @@ import type { UserProvidedValues, UiSettingsParams } from '@kbn/core-ui-settings-common'; +interface ValueValidation { + valid: boolean; + errorMessage?: string; +} + /** * Server-side client that provides access to the advanced settings stored in elasticsearch. * The settings provide control over the behavior of the Kibana application. @@ -57,4 +62,8 @@ export interface IUiSettingsClient { * Shows whether the uiSetting is a sensitive value. Used by telemetry to not send sensitive values. */ isSensitive: (key: string) => boolean; + /** + * Validates the uiSettings value and returns a ValueValidation object. + */ + validate: (key: string, value: unknown) => Promise; } diff --git a/packages/home/sample_data_card/src/sample_data_card.tsx b/packages/home/sample_data_card/src/sample_data_card.tsx index a8da0a7494da4..a952431c50971 100644 --- a/packages/home/sample_data_card/src/sample_data_card.tsx +++ b/packages/home/sample_data_card/src/sample_data_card.tsx @@ -6,11 +6,10 @@ * Side Public License, v 1. */ -import React, { useMemo } from 'react'; +import React from 'react'; import { useEuiTheme } from '@elastic/eui'; import type { SampleDataSet } from '@kbn/home-sample-data-types'; -import { useServices } from './services'; import { SampleDataCard as Component, Props as ComponentProps } from './sample_data_card.component'; /** @@ -27,12 +26,10 @@ export interface Props extends Pick { * function. */ export const SampleDataCard = ({ sampleDataSet, onStatusChange }: Props) => { - const { addBasePath } = useServices(); const { colorMode } = useEuiTheme(); const { darkPreviewImagePath, previewImagePath } = sampleDataSet; - const path = + const imagePath = colorMode === 'DARK' && darkPreviewImagePath ? darkPreviewImagePath : previewImagePath; - const imagePath = useMemo(() => addBasePath(path), [addBasePath, path]); return ; }; diff --git a/packages/kbn-apm-synthtrace-client/index.ts b/packages/kbn-apm-synthtrace-client/index.ts index 04bef11e3f657..c1f2bd25750c0 100644 --- a/packages/kbn-apm-synthtrace-client/index.ts +++ b/packages/kbn-apm-synthtrace-client/index.ts @@ -33,3 +33,4 @@ export { dedot } from './src/lib/utils/dedot'; export { generateLongId, generateShortId } from './src/lib/utils/generate_id'; export { appendHash, hashKeysOf } from './src/lib/utils/hash'; export type { ESDocumentWithOperation, SynthtraceESAction, SynthtraceGenerator } from './src/types'; +export { log, type LogDocument } from './src/lib/logs'; diff --git a/packages/kbn-apm-synthtrace-client/kibana.jsonc b/packages/kbn-apm-synthtrace-client/kibana.jsonc index 99055f3da4fe9..a50ec2be221d0 100644 --- a/packages/kbn-apm-synthtrace-client/kibana.jsonc +++ b/packages/kbn-apm-synthtrace-client/kibana.jsonc @@ -2,5 +2,5 @@ "type": "shared-common", "id": "@kbn/apm-synthtrace-client", "devOnly": true, - "owner": "@elastic/obs-ux-infra_services-team" + "owner": ["@elastic/obs-ux-infra_services-team", "@elastic/obs-ux-logs-team"] } diff --git a/packages/kbn-apm-synthtrace-client/src/lib/logs/index.ts b/packages/kbn-apm-synthtrace-client/src/lib/logs/index.ts new file mode 100644 index 0000000000000..8a1476cd58277 --- /dev/null +++ b/packages/kbn-apm-synthtrace-client/src/lib/logs/index.ts @@ -0,0 +1,77 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may 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 { Fields } from '../entity'; +import { Serializable } from '../serializable'; + +export type LogDocument = Fields & + Partial<{ + 'input.type': string; + 'log.file.path'?: string; + 'service.name'?: string; + 'data_stream.namespace': string; + 'data_stream.type': string; + 'data_stream.dataset': string; + message?: string; + 'event.dataset': string; + 'log.level'?: string; + 'host.name'?: string; + 'trace.id'?: string; + 'agent.name'?: string; + 'orchestrator.cluster.name'?: string; + 'orchestrator.cluster.id'?: string; + 'orchestrator.resource.id'?: string; + 'cloud.provider'?: string; + 'cloud.region'?: string; + 'cloud.availability_zone'?: string; + 'cloud.project.id'?: string; + 'cloud.instance.id'?: string; + }>; + +class Log extends Serializable { + service(name: string) { + this.fields['service.name'] = name; + return this; + } + + namespace(value: string) { + this.fields['data_stream.namespace'] = value; + return this; + } + + dataset(value: string) { + this.fields['data_stream.dataset'] = value; + this.fields['event.dataset'] = value; + return this; + } + + logLevel(level: string) { + this.fields['log.level'] = level; + return this; + } + + message(message: string) { + this.fields.message = message; + return this; + } +} + +function create(): Log { + return new Log({ + 'input.type': 'logs', + 'data_stream.namespace': 'default', + 'data_stream.type': 'logs', + 'data_stream.dataset': 'synth', + 'event.dataset': 'synth', + 'host.name': 'synth-host', + }); +} + +export const log = { + create, +}; diff --git a/packages/kbn-apm-synthtrace/README.md b/packages/kbn-apm-synthtrace/README.md index 6a6d0b726a5e4..6daad014ff0e5 100644 --- a/packages/kbn-apm-synthtrace/README.md +++ b/packages/kbn-apm-synthtrace/README.md @@ -21,6 +21,7 @@ This library can currently be used in two ways: - `Instance`: a single instance of a monitored service. E.g., the workload for a monitored service might be spread across multiple containers. An `Instance` object contains fields like `service.node.name` and `container.id`. - `Timerange`: an object that will return an array of timestamps based on an interval and a rate. These timestamps can be used to generate events/metricsets. - `Transaction`, `Span`, `APMError` and `Metricset`: events/metricsets that occur on an instance. For more background, see the [explanation of the APM data model](https://www.elastic.co/guide/en/apm/get-started/7.15/apm-data-model.html) +- `Log`: An instance of Log generating Service which supports additional helpers to customise fields like `messages`, `logLevel` #### Example @@ -109,12 +110,22 @@ node scripts/synthtrace simple_trace.ts --target=http://admin:changeme@localhost The script will try to automatically find bootstrapped APM indices. **If these indices do not exist, the script will exit with an error. It will not bootstrap the indices itself.** +### Understanding Scenario Files + +Scenario files accept 3 arguments, 2 of them optional and 1 mandatory + +| Arguments | Type | Description | +|-------------|:----------|------------------------------------------------------------------------------------------------------------------------------------------------------| +| `generate` | mandatory | This is the main function responsible for returning the events which will be indexed | +| `bootstrap` | optional | In case some setup needs to be done, before the data is generated, this function provides access to all available ES Clients to play with | +| `setClient` | optional | By default the apmEsClient used to generate data. If anyother client like logsEsClient needs to be used instead, this is where it should be returned | + The following options are supported: ### Connection options | Option | Type | Default | Description | -| ------------------- | -------- | :------ | ------------------------------------------------------------------------------------------ | +|---------------------|----------|:--------|--------------------------------------------------------------------------------------------| | `--target` | [string] | | Elasticsearch target | | `--kibana` | [string] | | Kibana target, used to bootstrap datastreams/mappings/templates/settings | | `--versionOverride` | [string] | | String to be used for `observer.version`. Defauls to the version of the installed package. | @@ -129,12 +140,11 @@ Note: ### Scenario options | Option | Type | Default | Description | -| ---------------- | --------- | :------ | ------------------------------------ | +|------------------|-----------|:--------|--------------------------------------| | `--from` | [date] | `now()` | The start of the time window | | `--to` | [date] | | The end of the time window | | `--live` | [boolean] | | Generate and index data continuously | | `--scenarioOpts` | | | Raw options specific to the scenario | - Note: - The default `--to` is `15m`. @@ -143,11 +153,12 @@ Note: ### Setup options -| Option | Type | Default | Description | -| ------------ | --------- | :------ | --------------------------------------- | -| `--clean` | [boolean] | `false` | Clean APM data before indexing new data | -| `--workers` | [number] | | Amount of Node.js worker threads | -| `--logLevel` | [enum] | `info` | Log level | +| Option | Type | Default | Description | +|--------------|-----------|:--------|-------------------------------------------------------------------------| +| `--clean` | [boolean] | `false` | Clean APM data before indexing new data | +| `--workers` | [number] | | Amount of Node.js worker threads | +| `--logLevel` | [enum] | `info` | Log level | +| `--type` | [string] | `apm` | Type of data to be generated, `log` must be passed when generating logs | ## Testing diff --git a/packages/kbn-apm-synthtrace/index.ts b/packages/kbn-apm-synthtrace/index.ts index 921243e67ac6a..880b97cac2a8f 100644 --- a/packages/kbn-apm-synthtrace/index.ts +++ b/packages/kbn-apm-synthtrace/index.ts @@ -17,6 +17,8 @@ export { AssetsSynthtraceEsClient } from './src/lib/assets/assets_synthtrace_es_ export { MonitoringSynthtraceEsClient } from './src/lib/monitoring/monitoring_synthtrace_es_client'; +export { LogsSynthtraceEsClient } from './src/lib/logs/logs_synthtrace_es_client'; + export { addObserverVersionTransform, deleteSummaryFieldTransform, diff --git a/packages/kbn-apm-synthtrace/kibana.jsonc b/packages/kbn-apm-synthtrace/kibana.jsonc index 1b3ef5b846149..9c85fa210bdd9 100644 --- a/packages/kbn-apm-synthtrace/kibana.jsonc +++ b/packages/kbn-apm-synthtrace/kibana.jsonc @@ -2,5 +2,5 @@ "type": "shared-server", "id": "@kbn/apm-synthtrace", "devOnly": true, - "owner": "@elastic/obs-ux-infra_services-team" + "owner": ["@elastic/obs-ux-infra_services-team", "@elastic/obs-ux-logs-team"] } diff --git a/packages/kbn-apm-synthtrace/src/cli/scenario.ts b/packages/kbn-apm-synthtrace/src/cli/scenario.ts index f89d335749326..0ba4665f0ee0e 100644 --- a/packages/kbn-apm-synthtrace/src/cli/scenario.ts +++ b/packages/kbn-apm-synthtrace/src/cli/scenario.ts @@ -6,17 +6,24 @@ * Side Public License, v 1. */ -import { SynthtraceGenerator, Timerange } from '@kbn/apm-synthtrace-client'; -import { Readable } from 'stream'; -import { ApmSynthtraceEsClient } from '../lib/apm/client/apm_synthtrace_es_client'; +import { Timerange } from '@kbn/apm-synthtrace-client'; import { Logger } from '../lib/utils/create_logger'; import { RunOptions } from './utils/parse_run_cli_flags'; +import { ApmSynthtraceEsClient, LogsSynthtraceEsClient } from '../..'; +import { ScenarioReturnType } from '../lib/utils/with_client'; type Generate = (options: { range: Timerange; -}) => SynthtraceGenerator | Array> | Readable; + clients: { + apmEsClient: ApmSynthtraceEsClient; + logsEsClient: LogsSynthtraceEsClient; + }; +}) => ScenarioReturnType | Array>; export type Scenario = (options: RunOptions & { logger: Logger }) => Promise<{ - bootstrap?: (options: { apmEsClient: ApmSynthtraceEsClient }) => Promise; + bootstrap?: (options: { + apmEsClient: ApmSynthtraceEsClient; + logsEsClient: LogsSynthtraceEsClient; + }) => Promise; generate: Generate; }>; diff --git a/packages/kbn-apm-synthtrace/src/cli/utils/bootstrap.ts b/packages/kbn-apm-synthtrace/src/cli/utils/bootstrap.ts index c12f6fc6beb51..be0bd7ff6168a 100644 --- a/packages/kbn-apm-synthtrace/src/cli/utils/bootstrap.ts +++ b/packages/kbn-apm-synthtrace/src/cli/utils/bootstrap.ts @@ -7,7 +7,8 @@ */ import { createLogger } from '../../lib/utils/create_logger'; -import { getEsClient } from './get_es_client'; +import { getApmEsClient } from './get_apm_es_client'; +import { getLogsEsClient } from './get_logs_es_client'; import { getKibanaClient } from './get_kibana_client'; import { getServiceUrls } from './get_service_urls'; import { RunOptions } from './parse_run_cli_flags'; @@ -26,22 +27,30 @@ export async function bootstrap(runOptions: RunOptions) { const version = runOptions.versionOverride || latestPackageVersion; - const apmEsClient = getEsClient({ + const apmEsClient = getApmEsClient({ target: esUrl, logger, concurrency: runOptions.concurrency, version, }); + const logsEsClient = getLogsEsClient({ + target: esUrl, + logger, + concurrency: runOptions.concurrency, + }); + await kibanaClient.installApmPackage(latestPackageVersion); if (runOptions.clean) { await apmEsClient.clean(); + await logsEsClient.clean(); } return { logger, apmEsClient, + logsEsClient, version, kibanaUrl, esUrl, diff --git a/packages/kbn-apm-synthtrace/src/cli/utils/get_es_client.ts b/packages/kbn-apm-synthtrace/src/cli/utils/get_apm_es_client.ts similarity index 87% rename from packages/kbn-apm-synthtrace/src/cli/utils/get_es_client.ts rename to packages/kbn-apm-synthtrace/src/cli/utils/get_apm_es_client.ts index e5caf0dcc22bd..ee350ab3c56d8 100644 --- a/packages/kbn-apm-synthtrace/src/cli/utils/get_es_client.ts +++ b/packages/kbn-apm-synthtrace/src/cli/utils/get_apm_es_client.ts @@ -7,11 +7,11 @@ */ import { Client } from '@elastic/elasticsearch'; -import { ApmSynthtraceEsClient } from '../../lib/apm/client/apm_synthtrace_es_client'; +import { ApmSynthtraceEsClient } from '../../..'; import { Logger } from '../../lib/utils/create_logger'; import { RunOptions } from './parse_run_cli_flags'; -export function getEsClient({ +export function getApmEsClient({ target, logger, version, diff --git a/packages/kbn-apm-synthtrace/src/cli/utils/get_logs_es_client.ts b/packages/kbn-apm-synthtrace/src/cli/utils/get_logs_es_client.ts new file mode 100644 index 0000000000000..8bfcdaef90839 --- /dev/null +++ b/packages/kbn-apm-synthtrace/src/cli/utils/get_logs_es_client.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 { Client } from '@elastic/elasticsearch'; +import { LogsSynthtraceEsClient } from '../../lib/logs/logs_synthtrace_es_client'; +import { Logger } from '../../lib/utils/create_logger'; +import { RunOptions } from './parse_run_cli_flags'; + +export function getLogsEsClient({ + target, + logger, + concurrency, +}: Pick & { + target: string; + logger: Logger; +}) { + const client = new Client({ + node: target, + }); + + return new LogsSynthtraceEsClient({ + client, + logger, + concurrency, + }); +} diff --git a/packages/kbn-apm-synthtrace/src/cli/utils/start_live_data_upload.ts b/packages/kbn-apm-synthtrace/src/cli/utils/start_live_data_upload.ts index 4fe29e3c94930..669ee9b3e3275 100644 --- a/packages/kbn-apm-synthtrace/src/cli/utils/start_live_data_upload.ts +++ b/packages/kbn-apm-synthtrace/src/cli/utils/start_live_data_upload.ts @@ -14,6 +14,7 @@ import { awaitStream } from '../../lib/utils/wait_until_stream_finished'; import { bootstrap } from './bootstrap'; import { getScenario } from './get_scenario'; import { RunOptions } from './parse_run_cli_flags'; +import { SynthtraceEsClient } from '../../lib/utils/with_client'; export async function startLiveDataUpload({ runOptions, @@ -24,7 +25,7 @@ export async function startLiveDataUpload({ }) { const file = runOptions.file; - const { logger, apmEsClient } = await bootstrap(runOptions); + const { logger, apmEsClient, logsEsClient } = await bootstrap(runOptions); const scenario = await getScenario({ file, logger }); const { generate } = await scenario({ ...runOptions, logger }); @@ -32,22 +33,22 @@ export async function startLiveDataUpload({ const bucketSizeInMs = 1000 * 60; let requestedUntil = start; - const stream = new PassThrough({ - objectMode: true, - }); + let currentStreams: PassThrough[] = []; + const cachedStreams: WeakMap = new WeakMap(); - apmEsClient.index(stream); + process.on('SIGINT', () => closeStreams()); + process.on('SIGTERM', () => closeStreams()); + process.on('SIGQUIT', () => closeStreams()); - function closeStream() { - stream.end(() => { - process.exit(0); + function closeStreams() { + currentStreams.forEach((stream) => { + stream.end(() => { + process.exit(0); + }); }); + currentStreams = []; // Reset the stream array } - process.on('SIGINT', closeStream); - process.on('SIGTERM', closeStream); - process.on('SIGQUIT', closeStream); - async function uploadNextBatch() { const now = Date.now(); @@ -59,22 +60,52 @@ export async function startLiveDataUpload({ `Requesting ${new Date(bucketFrom).toISOString()} to ${new Date(bucketTo).toISOString()}` ); - const next = logger.perf('execute_scenario', () => - generate({ range: timerange(bucketFrom.getTime(), bucketTo.getTime()) }) - ); + const generatorsAndClients = generate({ + range: timerange(bucketFrom.getTime(), bucketTo.getTime()), + clients: { logsEsClient, apmEsClient }, + }); + + const generatorsAndClientsArray = castArray(generatorsAndClients); + + const streams = generatorsAndClientsArray.map(({ client }) => { + let stream: PassThrough; + + if (cachedStreams.has(client)) { + stream = cachedStreams.get(client)!; + } else { + stream = new PassThrough({ objectMode: true }); + cachedStreams.set(client, stream); + client.index(stream); + } + + return stream; + }); - const concatenatedStream = castArray(next) - .reverse() - .reduce((prev, current) => { - const currentStream = isGeneratorObject(current) ? Readable.from(current) : current; - return currentStream.pipe(prev); - }, new PassThrough({ objectMode: true })); + currentStreams = streams; - concatenatedStream.pipe(stream, { end: false }); + const promises = generatorsAndClientsArray.map(({ generator }, i) => { + const concatenatedStream = castArray(generator) + .reverse() + .reduce((prev, current) => { + const currentStream = isGeneratorObject(current) ? Readable.from(current) : current; + return currentStream.pipe(prev); + }, new PassThrough({ objectMode: true })); - await awaitStream(concatenatedStream); + concatenatedStream.pipe(streams[i], { end: false }); - await apmEsClient.refresh(); + return awaitStream(concatenatedStream); + }); + + await Promise.all(promises); + + logger.info('Indexing completed'); + + const refreshPromise = generatorsAndClientsArray.map(async ({ client }) => { + await client.refresh(); + }); + + await Promise.all(refreshPromise); + logger.info('Refreshing completed'); requestedUntil = bucketTo; } @@ -85,6 +116,7 @@ export async function startLiveDataUpload({ await delay(bucketSizeInMs); } while (true); } + async function delay(ms: number) { return await new Promise((resolve) => setTimeout(resolve, ms)); } diff --git a/packages/kbn-apm-synthtrace/src/cli/utils/synthtrace_worker.ts b/packages/kbn-apm-synthtrace/src/cli/utils/synthtrace_worker.ts index 7617a9d58dd96..48a9bd60e5ac1 100644 --- a/packages/kbn-apm-synthtrace/src/cli/utils/synthtrace_worker.ts +++ b/packages/kbn-apm-synthtrace/src/cli/utils/synthtrace_worker.ts @@ -7,12 +7,14 @@ */ import { parentPort, workerData } from 'worker_threads'; import pidusage from 'pidusage'; +import { castArray } from 'lodash'; import { memoryUsage } from 'process'; import { timerange } from '@kbn/apm-synthtrace-client'; -import { getEsClient } from './get_es_client'; +import { getApmEsClient } from './get_apm_es_client'; import { getScenario } from './get_scenario'; import { loggerProxy } from './logger_proxy'; import { RunOptions } from './parse_run_cli_flags'; +import { getLogsEsClient } from './get_logs_es_client'; export interface WorkerData { bucketFrom: Date; @@ -27,13 +29,19 @@ const { bucketFrom, bucketTo, runOptions, esUrl, version } = workerData as Worke async function start() { const logger = loggerProxy; - const apmEsClient = getEsClient({ + const apmEsClient = getApmEsClient({ concurrency: runOptions.concurrency, target: esUrl, logger, version, }); + const logsEsClient = getLogsEsClient({ + concurrency: runOptions.concurrency, + target: esUrl, + logger, + }); + const file = runOptions.file; const scenario = await logger.perf('get_scenario', () => getScenario({ file, logger })); @@ -43,15 +51,17 @@ async function start() { const { generate, bootstrap } = await scenario({ ...runOptions, logger }); if (bootstrap) { - await bootstrap({ apmEsClient }); + await bootstrap({ apmEsClient, logsEsClient }); } logger.debug('Generating scenario'); - const generators = logger.perf('generate_scenario', () => - generate({ range: timerange(bucketFrom, bucketTo) }) + const generatorsAndClients = logger.perf('generate_scenario', () => + generate({ range: timerange(bucketFrom, bucketTo), clients: { logsEsClient, apmEsClient } }) ); + const generatorsAndClientsArray = castArray(generatorsAndClients); + logger.debug('Indexing scenario'); function mb(value: number): string { @@ -65,8 +75,12 @@ async function start() { }, 5000); await logger.perf('index_scenario', async () => { - await apmEsClient.index(generators); - await apmEsClient.refresh(); + const promises = generatorsAndClientsArray.map(async ({ client, generator }) => { + await client.index(generator); + await client.refresh(); + }); + + await Promise.all(promises); }); } diff --git a/packages/kbn-apm-synthtrace/src/lib/logs/logs_synthtrace_es_client.ts b/packages/kbn-apm-synthtrace/src/lib/logs/logs_synthtrace_es_client.ts new file mode 100644 index 0000000000000..8d2b32849bd8f --- /dev/null +++ b/packages/kbn-apm-synthtrace/src/lib/logs/logs_synthtrace_es_client.ts @@ -0,0 +1,61 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { Client } from '@elastic/elasticsearch'; +import { ESDocumentWithOperation } from '@kbn/apm-synthtrace-client'; +import { pipeline, Readable, Transform } from 'stream'; +import { LogDocument } from '@kbn/apm-synthtrace-client/src/lib/logs'; +import { SynthtraceEsClient, SynthtraceEsClientOptions } from '../shared/base_client'; +import { getSerializeTransform } from '../shared/get_serialize_transform'; +import { Logger } from '../utils/create_logger'; + +export type LogsSynthtraceEsClientOptions = Omit; + +export class LogsSynthtraceEsClient extends SynthtraceEsClient { + constructor(options: { client: Client; logger: Logger } & LogsSynthtraceEsClientOptions) { + super({ + ...options, + pipeline: logsPipeline(), + }); + this.dataStreams = ['logs-*-*']; + } +} + +function logsPipeline() { + return (base: Readable) => { + return pipeline( + base, + getSerializeTransform(), + getRoutingTransform(), + (err: unknown) => { + if (err) { + throw err; + } + } + ); + }; +} + +function getRoutingTransform() { + return new Transform({ + objectMode: true, + transform(document: ESDocumentWithOperation, encoding, callback) { + if ( + 'data_stream.type' in document && + 'data_stream.dataset' in document && + 'data_stream.namespace' in document + ) { + document._index = `${document['data_stream.type']}-${document['data_stream.dataset']}-${document['data_stream.namespace']}`; + } else { + throw new Error('Cannot determine index for event'); + } + + callback(null, document); + }, + }); +} diff --git a/packages/kbn-apm-synthtrace/src/lib/shared/get_serialize_transform.ts b/packages/kbn-apm-synthtrace/src/lib/shared/get_serialize_transform.ts index 26edb98429779..ed93c9502b722 100644 --- a/packages/kbn-apm-synthtrace/src/lib/shared/get_serialize_transform.ts +++ b/packages/kbn-apm-synthtrace/src/lib/shared/get_serialize_transform.ts @@ -9,13 +9,13 @@ import { ApmFields, Serializable } from '@kbn/apm-synthtrace-client'; import { Transform } from 'stream'; -export function getSerializeTransform() { - const buffer: ApmFields[] = []; +export function getSerializeTransform() { + const buffer: TFields[] = []; let cb: (() => void) | undefined; - function push(stream: Transform, events: ApmFields[], callback?: () => void) { - let event: ApmFields | undefined; + function push(stream: Transform, events: TFields[], callback?: () => void) { + let event: TFields | undefined; while ((event = events.shift())) { if (!stream.push(event)) { buffer.push(...events); @@ -37,7 +37,7 @@ export function getSerializeTransform() { push(this, nextEvents, nextCallback); } }, - write(chunk: Serializable, encoding, callback) { + write(chunk: Serializable, encoding, callback) { push(this, chunk.serialize(), callback); }, }); diff --git a/packages/kbn-apm-synthtrace/src/lib/utils/with_client.ts b/packages/kbn-apm-synthtrace/src/lib/utils/with_client.ts new file mode 100644 index 0000000000000..68dc780ac6464 --- /dev/null +++ b/packages/kbn-apm-synthtrace/src/lib/utils/with_client.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. + */ + +import { SynthtraceGenerator } from '@kbn/apm-synthtrace-client'; +import { Readable } from 'stream'; +import { ApmSynthtraceEsClient, LogsSynthtraceEsClient } from '../../..'; + +export type SynthtraceEsClient = ApmSynthtraceEsClient | LogsSynthtraceEsClient; +export type SynthGenerator = + | SynthtraceGenerator + | Array> + | Readable; + +export const withClient = ( + client: SynthtraceEsClient, + generator: SynthGenerator +) => { + return { + client, + generator, + }; +}; + +export type ScenarioReturnType = ReturnType>; diff --git a/packages/kbn-apm-synthtrace/src/scenarios/agent_config.ts b/packages/kbn-apm-synthtrace/src/scenarios/agent_config.ts index 7f72e27193756..e77a16bef6c14 100644 --- a/packages/kbn-apm-synthtrace/src/scenarios/agent_config.ts +++ b/packages/kbn-apm-synthtrace/src/scenarios/agent_config.ts @@ -7,21 +7,25 @@ */ import { observer, AgentConfigFields } from '@kbn/apm-synthtrace-client'; import { Scenario } from '../cli/scenario'; +import { withClient } from '../lib/utils/with_client'; const scenario: Scenario = async ({ logger }) => { return { - generate: ({ range }) => { + generate: ({ range, clients: { apmEsClient } }) => { const agentConfig = observer().agentConfig(); - return range - .interval('30s') - .rate(1) - .generator((timestamp) => { - const events = logger.perf('generating_agent_config_events', () => { - return agentConfig.etag('test-etag').timestamp(timestamp); - }); - return events; - }); + return withClient( + apmEsClient, + range + .interval('30s') + .rate(1) + .generator((timestamp) => { + const events = logger.perf('generating_agent_config_events', () => { + return agentConfig.etag('test-etag').timestamp(timestamp); + }); + return events; + }) + ); }, }; }; diff --git a/packages/kbn-apm-synthtrace/src/scenarios/aws_lambda.ts b/packages/kbn-apm-synthtrace/src/scenarios/aws_lambda.ts index 9b5ed599fa2fb..44f11b05d90cf 100644 --- a/packages/kbn-apm-synthtrace/src/scenarios/aws_lambda.ts +++ b/packages/kbn-apm-synthtrace/src/scenarios/aws_lambda.ts @@ -10,12 +10,13 @@ import { apm, ApmFields } from '@kbn/apm-synthtrace-client'; import { Scenario } from '../cli/scenario'; import { RunOptions } from '../cli/utils/parse_run_cli_flags'; import { getSynthtraceEnvironment } from '../lib/utils/get_synthtrace_environment'; +import { withClient } from '../lib/utils/with_client'; const ENVIRONMENT = getSynthtraceEnvironment(__filename); const scenario: Scenario = async (runOptions: RunOptions) => { return { - generate: ({ range }) => { + generate: ({ range, clients: { apmEsClient } }) => { const timestamps = range.ratePerMinute(180); const cloudFields: ApmFields = { @@ -91,7 +92,7 @@ const scenario: Scenario = async (runOptions: RunOptions) => { ]; }); - return awsLambdaEvents; + return withClient(apmEsClient, awsLambdaEvents); }, }; }; diff --git a/packages/kbn-apm-synthtrace/src/scenarios/azure_functions.ts b/packages/kbn-apm-synthtrace/src/scenarios/azure_functions.ts index 070b6218183b8..69be0a5b157e8 100644 --- a/packages/kbn-apm-synthtrace/src/scenarios/azure_functions.ts +++ b/packages/kbn-apm-synthtrace/src/scenarios/azure_functions.ts @@ -10,12 +10,13 @@ import { apm, ApmFields } from '@kbn/apm-synthtrace-client'; import { Scenario } from '../cli/scenario'; import { RunOptions } from '../cli/utils/parse_run_cli_flags'; import { getSynthtraceEnvironment } from '../lib/utils/get_synthtrace_environment'; +import { withClient } from '../lib/utils/with_client'; const ENVIRONMENT = getSynthtraceEnvironment(__filename); const scenario: Scenario = async (runOptions: RunOptions) => { return { - generate: ({ range }) => { + generate: ({ range, clients: { apmEsClient } }) => { const timestamps = range.ratePerMinute(180); const cloudFields: ApmFields = { @@ -61,7 +62,7 @@ const scenario: Scenario = async (runOptions: RunOptions) => { ]; }); - return awsLambdaEvents; + return withClient(apmEsClient, awsLambdaEvents); }, }; }; diff --git a/packages/kbn-apm-synthtrace/src/scenarios/cloud_services_icons.ts b/packages/kbn-apm-synthtrace/src/scenarios/cloud_services_icons.ts index c4ee421dbab4a..3c7ee8d6566cd 100644 --- a/packages/kbn-apm-synthtrace/src/scenarios/cloud_services_icons.ts +++ b/packages/kbn-apm-synthtrace/src/scenarios/cloud_services_icons.ts @@ -9,6 +9,7 @@ import { apm, ApmFields, Instance } from '@kbn/apm-synthtrace-client'; import { Scenario } from '../cli/scenario'; import { getSynthtraceEnvironment } from '../lib/utils/get_synthtrace_environment'; +import { withClient } from '../lib/utils/with_client'; const ENVIRONMENT = getSynthtraceEnvironment(__filename); @@ -16,7 +17,7 @@ const scenario: Scenario = async ({ logger, scenarioOpts }) => { const { numServices = 3 } = scenarioOpts || {}; return { - generate: ({ range }) => { + generate: ({ range, clients: { apmEsClient } }) => { const transactionName = 'Azure-AWS-Transaction'; const successfulTimestamps = range.ratePerMinute(60); @@ -176,7 +177,10 @@ const scenario: Scenario = async ({ logger, scenarioOpts }) => { return successfulTraceEvents; }; - return logger.perf('generating_apm_events', () => instances.flatMap(instanceSpans)); + return withClient( + apmEsClient, + logger.perf('generating_apm_events', () => instances.flatMap(instanceSpans)) + ); }, }; }; diff --git a/packages/kbn-apm-synthtrace/src/scenarios/continuous_rollups.ts b/packages/kbn-apm-synthtrace/src/scenarios/continuous_rollups.ts index 0a346dcf99542..4b1a62a800430 100644 --- a/packages/kbn-apm-synthtrace/src/scenarios/continuous_rollups.ts +++ b/packages/kbn-apm-synthtrace/src/scenarios/continuous_rollups.ts @@ -11,6 +11,7 @@ import { merge, range as lodashRange } from 'lodash'; import { Scenario } from '../cli/scenario'; import { ComponentTemplateName } from '../lib/apm/client/apm_synthtrace_es_client'; import { getSynthtraceEnvironment } from '../lib/utils/get_synthtrace_environment'; +import { withClient } from '../lib/utils/with_client'; const ENVIRONMENTS = ['production', 'development'].map((env) => getSynthtraceEnvironment(__filename, env) @@ -40,7 +41,7 @@ const scenario: Scenario = async ({ logger, scenarioOpts }) => { } ); }, - generate: ({ range }) => { + generate: ({ range, clients: { apmEsClient } }) => { const TRANSACTION_TYPES = ['request', 'custom']; const MIN_DURATION = 10; @@ -64,36 +65,39 @@ const scenario: Scenario = async ({ logger, scenarioOpts }) => { const transactionGroupRange = lodashRange(0, numTxGroups); - return range - .interval('1m') - .rate(1) - .generator((timestamp, timestampIndex) => { - return logger.perf( - 'generate_events_for_timestamp ' + new Date(timestamp).toISOString(), - () => { - const events = instances.flatMap((instance) => - transactionGroupRange.flatMap((groupId, groupIndex) => - OUTCOMES.map((outcome) => { - const duration = Math.round( - (timestampIndex % MAX_BUCKETS) * BUCKET_SIZE + MIN_DURATION - ); - - return instance - .transaction( - `transaction-${groupId}`, - TRANSACTION_TYPES[groupIndex % TRANSACTION_TYPES.length] - ) - .timestamp(timestamp) - .duration(duration) - .outcome(outcome); - }) - ) - ); - - return events; - } - ); - }); + return withClient( + apmEsClient, + range + .interval('1m') + .rate(1) + .generator((timestamp, timestampIndex) => { + return logger.perf( + 'generate_events_for_timestamp ' + new Date(timestamp).toISOString(), + () => { + const events = instances.flatMap((instance) => + transactionGroupRange.flatMap((groupId, groupIndex) => + OUTCOMES.map((outcome) => { + const duration = Math.round( + (timestampIndex % MAX_BUCKETS) * BUCKET_SIZE + MIN_DURATION + ); + + return instance + .transaction( + `transaction-${groupId}`, + TRANSACTION_TYPES[groupIndex % TRANSACTION_TYPES.length] + ) + .timestamp(timestamp) + .duration(duration) + .outcome(outcome); + }) + ) + ); + + return events; + } + ); + }) + ); }, }; }; diff --git a/packages/kbn-apm-synthtrace/src/scenarios/distributed_trace.ts b/packages/kbn-apm-synthtrace/src/scenarios/distributed_trace.ts index c47e10733fd5f..5b591078c46bf 100644 --- a/packages/kbn-apm-synthtrace/src/scenarios/distributed_trace.ts +++ b/packages/kbn-apm-synthtrace/src/scenarios/distributed_trace.ts @@ -11,12 +11,13 @@ import { Scenario } from '../cli/scenario'; import { RunOptions } from '../cli/utils/parse_run_cli_flags'; import { getSynthtraceEnvironment } from '../lib/utils/get_synthtrace_environment'; +import { withClient } from '../lib/utils/with_client'; const ENVIRONMENT = getSynthtraceEnvironment(__filename); const scenario: Scenario = async (runOptions: RunOptions) => { return { - generate: ({ range }) => { + generate: ({ range, clients: { apmEsClient } }) => { const transactionName = '240rpm/75% 1000ms'; const successfulTimestamps = range.interval('1s').rate(3); @@ -86,7 +87,7 @@ const scenario: Scenario = async (runOptions: RunOptions) => { ); }); - return traces; + return withClient(apmEsClient, traces); }, }; }; diff --git a/packages/kbn-apm-synthtrace/src/scenarios/distributed_trace_long.ts b/packages/kbn-apm-synthtrace/src/scenarios/distributed_trace_long.ts index cd4b719494b56..d298a76ffccae 100644 --- a/packages/kbn-apm-synthtrace/src/scenarios/distributed_trace_long.ts +++ b/packages/kbn-apm-synthtrace/src/scenarios/distributed_trace_long.ts @@ -12,12 +12,13 @@ import { apm, ApmFields, DistributedTrace } from '@kbn/apm-synthtrace-client'; import { Scenario } from '../cli/scenario'; import { RunOptions } from '../cli/utils/parse_run_cli_flags'; import { getSynthtraceEnvironment } from '../lib/utils/get_synthtrace_environment'; +import { withClient } from '../lib/utils/with_client'; const ENVIRONMENT = getSynthtraceEnvironment(__filename); const scenario: Scenario = async (runOptions: RunOptions) => { return { - generate: ({ range }) => { + generate: ({ range, clients: { apmEsClient } }) => { const ratePerMinute = 1; const traceDuration = 1100; const rootTransactionName = `${ratePerMinute}rpm / ${traceDuration}ms`; @@ -122,7 +123,7 @@ const scenario: Scenario = async (runOptions: RunOptions) => { }).getTransaction(); }); - return traces; + return withClient(apmEsClient, traces); }, }; }; diff --git a/packages/kbn-apm-synthtrace/src/scenarios/high_throughput.ts b/packages/kbn-apm-synthtrace/src/scenarios/high_throughput.ts index 2e7d8c22a4696..70988d16a0744 100644 --- a/packages/kbn-apm-synthtrace/src/scenarios/high_throughput.ts +++ b/packages/kbn-apm-synthtrace/src/scenarios/high_throughput.ts @@ -10,6 +10,7 @@ import { random } from 'lodash'; import { apm, Instance, ApmFields } from '@kbn/apm-synthtrace-client'; import { Scenario } from '../cli/scenario'; import { getSynthtraceEnvironment } from '../lib/utils/get_synthtrace_environment'; +import { withClient } from '../lib/utils/with_client'; const ENVIRONMENT = getSynthtraceEnvironment(__filename); @@ -18,7 +19,7 @@ const scenario: Scenario = async ({ logger }) => { const services = ['web', 'order-processing', 'api-backend']; return { - generate: ({ range }) => { + generate: ({ range, clients: { apmEsClient } }) => { const successfulTimestamps = range.interval('1s'); const instances = services.map((service, index) => @@ -95,10 +96,13 @@ const scenario: Scenario = async ({ logger }) => { return successfulTraceEvents; }; - return logger.perf('generating_apm_events', () => - instances - .flatMap((instance) => urls.map((url) => ({ instance, url }))) - .map(({ instance, url }, index) => instanceSpans(instance, url, index)) + return withClient( + apmEsClient, + logger.perf('generating_apm_events', () => + instances + .flatMap((instance) => urls.map((url) => ({ instance, url }))) + .map(({ instance, url }, index) => instanceSpans(instance, url, index)) + ) ); }, }; diff --git a/packages/kbn-apm-synthtrace/src/scenarios/logs_and_metrics.ts b/packages/kbn-apm-synthtrace/src/scenarios/logs_and_metrics.ts new file mode 100644 index 0000000000000..7532b3dc9477c --- /dev/null +++ b/packages/kbn-apm-synthtrace/src/scenarios/logs_and_metrics.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 and the Server Side Public License, v 1; you may 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 { + LogDocument, + log, + generateShortId, + generateLongId, + apm, + Instance, +} from '@kbn/apm-synthtrace-client'; +import { Scenario } from '../cli/scenario'; +import { withClient } from '../lib/utils/with_client'; +import { getSynthtraceEnvironment } from '../lib/utils/get_synthtrace_environment'; + +const ENVIRONMENT = getSynthtraceEnvironment(__filename); + +const scenario: Scenario = async (runOptions) => { + return { + generate: ({ range, clients: { logsEsClient, apmEsClient } }) => { + const { numServices = 3 } = runOptions.scenarioOpts || {}; + const { logger } = runOptions; + + // Logs Data logic + const MESSAGE_LOG_LEVELS = [ + { message: 'A simple log', level: 'info' }, + { message: 'Yet another debug log', level: 'debug' }, + { message: 'Error with certificate: "ca_trusted_fingerprint"', level: 'error' }, + ]; + const CLOUD_PROVIDERS = ['gcp', 'aws', 'azure']; + const CLOUD_REGION = ['eu-central-1', 'us-east-1', 'area-51']; + + const CLUSTER = [ + { clusterId: generateShortId(), clusterName: 'synth-cluster-1' }, + { clusterId: generateShortId(), clusterName: 'synth-cluster-2' }, + { clusterId: generateShortId(), clusterName: 'synth-cluster-3' }, + ]; + + const SERVICE_NAMES = Array(3) + .fill(null) + .map((_, idx) => `synth-service-${idx}`); + + const logs = range + .interval('1m') + .rate(1) + .generator((timestamp) => { + return Array(20) + .fill(0) + .map(() => { + const index = Math.floor(Math.random() * 3); + return log + .create() + .message(MESSAGE_LOG_LEVELS[index].message) + .logLevel(MESSAGE_LOG_LEVELS[index].level) + .service(SERVICE_NAMES[index]) + .defaults({ + 'trace.id': generateShortId(), + 'agent.name': 'synth-agent', + 'orchestrator.cluster.name': CLUSTER[index].clusterName, + 'orchestrator.cluster.id': CLUSTER[index].clusterId, + 'orchestrator.resource.id': generateShortId(), + 'cloud.provider': CLOUD_PROVIDERS[Math.floor(Math.random() * 3)], + 'cloud.region': CLOUD_REGION[index], + 'cloud.availability_zone': `${CLOUD_REGION[index]}a`, + 'cloud.project.id': generateShortId(), + 'cloud.instance.id': generateShortId(), + 'log.file.path': `/logs/${generateLongId()}/error.txt`, + }) + .timestamp(timestamp); + }); + }); + + // APM Simple Trace + + const transactionName = '240rpm/75% 1000ms'; + + const successfulTimestamps = range.interval('1m').rate(180); + const failedTimestamps = range.interval('1m').rate(180); + + const instances = [...Array(numServices).keys()].map((index) => + apm + .service({ name: SERVICE_NAMES[index], environment: ENVIRONMENT, agentName: 'go' }) + .instance('instance') + ); + const instanceSpans = (instance: Instance) => { + const successfulTraceEvents = successfulTimestamps.generator((timestamp) => + instance + .transaction({ transactionName }) + .timestamp(timestamp) + .duration(1000) + .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) + ) + ); + + const failedTraceEvents = failedTimestamps.generator((timestamp) => + instance + .transaction({ transactionName }) + .timestamp(timestamp) + .duration(1000) + .failure() + .errors( + instance + .error({ message: '[ResponseError] index_not_found_exception' }) + .timestamp(timestamp + 50) + ) + ); + + const metricsets = range + .interval('30s') + .rate(1) + .generator((timestamp) => + instance + .appMetrics({ + 'system.memory.actual.free': 800, + 'system.memory.total': 1000, + 'system.cpu.total.norm.pct': 0.6, + 'system.process.cpu.total.norm.pct': 0.7, + }) + .timestamp(timestamp) + ); + + return [successfulTraceEvents, failedTraceEvents, metricsets]; + }; + + return [ + withClient( + logsEsClient, + logger.perf('generating_logs', () => logs) + ), + withClient( + apmEsClient, + logger.perf('generating_apm_events', () => + instances.flatMap((instance) => instanceSpans(instance)) + ) + ), + ]; + }, + }; +}; + +export default scenario; diff --git a/packages/kbn-apm-synthtrace/src/scenarios/low_throughput.ts b/packages/kbn-apm-synthtrace/src/scenarios/low_throughput.ts index 8a79706289cea..de54a7a721911 100644 --- a/packages/kbn-apm-synthtrace/src/scenarios/low_throughput.ts +++ b/packages/kbn-apm-synthtrace/src/scenarios/low_throughput.ts @@ -10,6 +10,7 @@ import { ApmFields, Instance, apm } from '@kbn/apm-synthtrace-client'; import { random } from 'lodash'; import { Scenario } from '../cli/scenario'; import { getSynthtraceEnvironment } from '../lib/utils/get_synthtrace_environment'; +import { withClient } from '../lib/utils/with_client'; const ENVIRONMENT = getSynthtraceEnvironment(__filename); @@ -18,7 +19,7 @@ const scenario: Scenario = async ({ logger }) => { const services = ['web', 'order-processing', 'api-backend']; return { - generate: ({ range }) => { + generate: ({ range, clients: { apmEsClient } }) => { const successfulTimestamps = range.ratePerMinute(60); const instances = services.map((serviceName, index) => @@ -78,10 +79,13 @@ const scenario: Scenario = async ({ logger }) => { return successfulTraceEvents; }; - return logger.perf('generating_apm_events', () => - instances - .flatMap((instance) => urls.map((url) => ({ instance, url }))) - .map(({ instance, url }, index) => instanceSpans(instance, url, index)) + return withClient( + apmEsClient, + logger.perf('generating_apm_events', () => + instances + .flatMap((instance) => urls.map((url) => ({ instance, url }))) + .map(({ instance, url }, index) => instanceSpans(instance, url, index)) + ) ); }, }; diff --git a/packages/kbn-apm-synthtrace/src/scenarios/many_services.ts b/packages/kbn-apm-synthtrace/src/scenarios/many_services.ts index 14bd5d9a70042..705d425d8d932 100644 --- a/packages/kbn-apm-synthtrace/src/scenarios/many_services.ts +++ b/packages/kbn-apm-synthtrace/src/scenarios/many_services.ts @@ -10,6 +10,7 @@ import { ApmFields, apm, Instance } from '@kbn/apm-synthtrace-client'; import { flatten, random } from 'lodash'; import { Scenario } from '../cli/scenario'; import { getSynthtraceEnvironment } from '../lib/utils/get_synthtrace_environment'; +import { withClient } from '../lib/utils/with_client'; const ENVIRONMENT = getSynthtraceEnvironment(__filename); @@ -25,7 +26,7 @@ const scenario: Scenario = async ({ logger }) => { }; return { - generate: ({ range }) => { + generate: ({ range, clients: { apmEsClient } }) => { const successfulTimestamps = range.ratePerMinute(180); const instances = flatten( @@ -95,10 +96,13 @@ const scenario: Scenario = async ({ logger }) => { return successfulTraceEvents; }; - return logger.perf('generating_apm_events', () => - instances - .flatMap((instance) => urls.map((url) => ({ instance, url }))) - .map(({ instance, url }) => instanceSpans(instance, url)) + return withClient( + apmEsClient, + logger.perf('generating_apm_events', () => + instances + .flatMap((instance) => urls.map((url) => ({ instance, url }))) + .map(({ instance, url }) => instanceSpans(instance, url)) + ) ); }, }; diff --git a/packages/kbn-apm-synthtrace/src/scenarios/many_transactions_per_service.ts b/packages/kbn-apm-synthtrace/src/scenarios/many_transactions_per_service.ts index e814ed51b08e6..565ac8ea4f1ab 100644 --- a/packages/kbn-apm-synthtrace/src/scenarios/many_transactions_per_service.ts +++ b/packages/kbn-apm-synthtrace/src/scenarios/many_transactions_per_service.ts @@ -8,6 +8,7 @@ import { ApmFields, apm, Instance } from '@kbn/apm-synthtrace-client'; import { Scenario } from '../cli/scenario'; import { getSynthtraceEnvironment } from '../lib/utils/get_synthtrace_environment'; +import { withClient } from '../lib/utils/with_client'; const ENVIRONMENT = getSynthtraceEnvironment(__filename); @@ -17,7 +18,7 @@ const scenario: Scenario = async (runOptions) => { const numTransactions = 100; return { - generate: ({ range }) => { + generate: ({ range, clients: { apmEsClient } }) => { const urls = ['GET /order', 'POST /basket', 'DELETE /basket', 'GET /products']; const successfulTimestamps = range.ratePerMinute(180); @@ -68,14 +69,17 @@ const scenario: Scenario = async (runOptions) => { return [successfulTraceEvents, failedTraceEvents, metricsets]; }; - return logger.perf('generating_apm_events', () => - instances - .flatMap((instance) => - transactionNames.map((transactionName) => ({ instance, transactionName })) - ) - .flatMap(({ instance, transactionName }, index) => - instanceSpans(instance, transactionName) - ) + return withClient( + apmEsClient, + logger.perf('generating_apm_events', () => + instances + .flatMap((instance) => + transactionNames.map((transactionName) => ({ instance, transactionName })) + ) + .flatMap(({ instance, transactionName }, index) => + instanceSpans(instance, transactionName) + ) + ) ); }, }; diff --git a/packages/kbn-apm-synthtrace/src/scenarios/mobile.ts b/packages/kbn-apm-synthtrace/src/scenarios/mobile.ts index 0ca4abf07bf91..594bd0b875324 100644 --- a/packages/kbn-apm-synthtrace/src/scenarios/mobile.ts +++ b/packages/kbn-apm-synthtrace/src/scenarios/mobile.ts @@ -15,6 +15,7 @@ import type { } from '@kbn/apm-synthtrace-client'; import { Scenario } from '../cli/scenario'; import { getSynthtraceEnvironment } from '../lib/utils/get_synthtrace_environment'; +import { withClient } from '../lib/utils/with_client'; const ENVIRONMENT = getSynthtraceEnvironment(__filename); @@ -328,7 +329,7 @@ const scenario: Scenario = async ({ scenarioOpts, logger }) => { const { numDevices = 10 } = scenarioOpts || {}; return { - generate: ({ range }) => { + generate: ({ range, clients: { apmEsClient } }) => { const androidDevices = [...Array(numDevices).keys()].map((index) => { const deviceMetadata = ANDROID_DEVICES[randomInt(ANDROID_DEVICES.length)]; const geoNetwork = GEO_AND_NETWORK[randomInt(GEO_AND_NETWORK.length)]; @@ -444,13 +445,13 @@ const scenario: Scenario = async ({ scenarioOpts, logger }) => { ); }; - return [ + return withClient(apmEsClient, [ ...androidDevices.flatMap((device) => [ sessionTransactions(device), appLaunchMetrics(device), ]), ...iOSDevices.map((device) => sessionTransactions(device)), - ]; + ]); }, }; }; diff --git a/packages/kbn-apm-synthtrace/src/scenarios/other_bucket_group.ts b/packages/kbn-apm-synthtrace/src/scenarios/other_bucket_group.ts index 49fcc2f6ac47b..db0de7e5a5b32 100644 --- a/packages/kbn-apm-synthtrace/src/scenarios/other_bucket_group.ts +++ b/packages/kbn-apm-synthtrace/src/scenarios/other_bucket_group.ts @@ -9,6 +9,7 @@ import { apm, ApmFields } from '@kbn/apm-synthtrace-client'; import { range as lodashRange } from 'lodash'; import { Scenario } from '../cli/scenario'; import { getSynthtraceEnvironment } from '../lib/utils/get_synthtrace_environment'; +import { withClient } from '../lib/utils/with_client'; const ENVIRONMENTS = ['production', 'development'].map((env) => getSynthtraceEnvironment(__filename, env) @@ -18,7 +19,7 @@ const scenario: Scenario = async ({ logger, scenarioOpts }) => { const { services: numServices = 10, txGroups: numTxGroups = 10 } = scenarioOpts ?? {}; return { - generate: ({ range }) => { + generate: ({ range, clients: { apmEsClient } }) => { const TRANSACTION_TYPES = ['request']; const MIN_DURATION = 10; @@ -46,41 +47,47 @@ const scenario: Scenario = async ({ logger, scenarioOpts }) => { '_other', ]; - return range - .interval('1m') - .rate(1) - .generator((timestamp, timestampIndex) => { - return logger.perf( - 'generate_events_for_timestamp ' + new Date(timestamp).toISOString(), - () => { - const events = instances.flatMap((instance) => - transactionGroupRange.flatMap((groupId, groupIndex) => { - const duration = Math.round( - (timestampIndex % MAX_BUCKETS) * BUCKET_SIZE + MIN_DURATION - ); + return withClient( + apmEsClient, + range + .interval('1m') + .rate(1) + .generator((timestamp, timestampIndex) => { + return logger.perf( + 'generate_events_for_timestamp ' + new Date(timestamp).toISOString(), + () => { + const events = instances.flatMap((instance) => + transactionGroupRange.flatMap((groupId, groupIndex) => { + const duration = Math.round( + (timestampIndex % MAX_BUCKETS) * BUCKET_SIZE + MIN_DURATION + ); + + if (groupId === '_other') { + return instance + .transaction(groupId) + .timestamp(timestamp) + .duration(duration) + .defaults({ + 'transaction.aggregation.overflow_count': 10, + }); + } - if (groupId === '_other') { return instance - .transaction(groupId) + .transaction( + groupId, + TRANSACTION_TYPES[groupIndex % TRANSACTION_TYPES.length] + ) .timestamp(timestamp) .duration(duration) - .defaults({ - 'transaction.aggregation.overflow_count': 10, - }); - } - - return instance - .transaction(groupId, TRANSACTION_TYPES[groupIndex % TRANSACTION_TYPES.length]) - .timestamp(timestamp) - .duration(duration) - .success(); - }) - ); + .success(); + }) + ); - return events; - } - ); - }); + return events; + } + ); + }) + ); }, }; }; diff --git a/packages/kbn-apm-synthtrace/src/scenarios/service_map.ts b/packages/kbn-apm-synthtrace/src/scenarios/service_map.ts index f39d4bdd1e221..2c6c75e4dfe81 100644 --- a/packages/kbn-apm-synthtrace/src/scenarios/service_map.ts +++ b/packages/kbn-apm-synthtrace/src/scenarios/service_map.ts @@ -10,67 +10,71 @@ import { ApmFields, serviceMap } from '@kbn/apm-synthtrace-client'; import { Scenario } from '../cli/scenario'; import { RunOptions } from '../cli/utils/parse_run_cli_flags'; import { getSynthtraceEnvironment } from '../lib/utils/get_synthtrace_environment'; +import { withClient } from '../lib/utils/with_client'; const environment = getSynthtraceEnvironment(__filename); const scenario: Scenario = async (runOptions: RunOptions) => { return { - generate: ({ range }) => { - return range - .interval('1s') - .rate(3) - .generator( - serviceMap({ - services: [ - { 'frontend-rum': 'rum-js' }, - { 'frontend-node': 'nodejs' }, - { advertService: 'java' }, - { checkoutService: 'go' }, - { cartService: 'dotnet' }, - { paymentService: 'nodejs' }, - { productCatalogService: 'go' }, - ], - environment, - definePaths([rum, node, adv, chk, cart, pay, prod]) { - return [ - [ - [rum, 'fetchAd'], - [node, 'GET /nodejs/adTag'], - [adv, 'APIRestController#getAd'], - ['elasticsearch', 'GET ad-*/_search'], - ], - [ - [rum, 'AddToCart'], - [node, 'POST /nodejs/addToCart'], - [cart, 'POST /dotnet/reserveProduct'], - ['redis', 'DECR inventory:i012345:stock'], - ], - [ - [rum, 'Checkout'], - [node, 'POST /nodejs/placeOrder'], - [chk, 'POST /go/placeOrder'], - [pay, 'POST /nodejs/processPayment'], - ], - [ - [chk, 'POST /go/clearCart'], - [cart, 'PUT /dotnet/cart/c12345/reset'], - ['redis', 'INCR inventory:i012345:stock'], - ], - [ - [rum, 'ProductDashboard'], - [node, 'GET /nodejs/products'], - [prod, 'GET /go/product-catalog'], - ['elasticsearch', 'GET product-*/_search'], - ], - [ - [chk, 'PUT /go/update-inventory'], - [prod, 'PUT /go/product/i012345'], - ], - [pay], - ]; - }, - }) - ); + generate: ({ range, clients: { apmEsClient } }) => { + return withClient( + apmEsClient, + range + .interval('1s') + .rate(3) + .generator( + serviceMap({ + services: [ + { 'frontend-rum': 'rum-js' }, + { 'frontend-node': 'nodejs' }, + { advertService: 'java' }, + { checkoutService: 'go' }, + { cartService: 'dotnet' }, + { paymentService: 'nodejs' }, + { productCatalogService: 'go' }, + ], + environment, + definePaths([rum, node, adv, chk, cart, pay, prod]) { + return [ + [ + [rum, 'fetchAd'], + [node, 'GET /nodejs/adTag'], + [adv, 'APIRestController#getAd'], + ['elasticsearch', 'GET ad-*/_search'], + ], + [ + [rum, 'AddToCart'], + [node, 'POST /nodejs/addToCart'], + [cart, 'POST /dotnet/reserveProduct'], + ['redis', 'DECR inventory:i012345:stock'], + ], + [ + [rum, 'Checkout'], + [node, 'POST /nodejs/placeOrder'], + [chk, 'POST /go/placeOrder'], + [pay, 'POST /nodejs/processPayment'], + ], + [ + [chk, 'POST /go/clearCart'], + [cart, 'PUT /dotnet/cart/c12345/reset'], + ['redis', 'INCR inventory:i012345:stock'], + ], + [ + [rum, 'ProductDashboard'], + [node, 'GET /nodejs/products'], + [prod, 'GET /go/product-catalog'], + ['elasticsearch', 'GET product-*/_search'], + ], + [ + [chk, 'PUT /go/update-inventory'], + [prod, 'PUT /go/product/i012345'], + ], + [pay], + ]; + }, + }) + ) + ); }, }; }; diff --git a/packages/kbn-apm-synthtrace/src/scenarios/service_map_oom.ts b/packages/kbn-apm-synthtrace/src/scenarios/service_map_oom.ts index 30f0a8c58e577..7c0d4dbbc8475 100644 --- a/packages/kbn-apm-synthtrace/src/scenarios/service_map_oom.ts +++ b/packages/kbn-apm-synthtrace/src/scenarios/service_map_oom.ts @@ -10,18 +10,18 @@ import { ApmFields, httpExitSpan } from '@kbn/apm-synthtrace-client'; import { service } from '@kbn/apm-synthtrace-client/src/lib/apm/service'; import { Transaction } from '@kbn/apm-synthtrace-client/src/lib/apm/transaction'; import { Scenario } from '../cli/scenario'; -import { RunOptions } from '../cli/utils/parse_run_cli_flags'; import { getSynthtraceEnvironment } from '../lib/utils/get_synthtrace_environment'; +import { withClient } from '../lib/utils/with_client'; const environment = getSynthtraceEnvironment(__filename); -const scenario: Scenario = async (runOptions: RunOptions) => { +const scenario: Scenario = async () => { const numServices = 500; const tracesPerMinute = 10; return { - generate: ({ range }) => { + generate: ({ range, clients: { apmEsClient } }) => { const services = new Array(numServices) .fill(undefined) .map((_, idx) => { @@ -29,34 +29,37 @@ const scenario: Scenario = async (runOptions: RunOptions) => { }) .reverse(); - return range.ratePerMinute(tracesPerMinute).generator((timestamp) => { - const rootTransaction = services.reduce((prev, currentService) => { - const tx = currentService - .transaction(`GET /my/function`, 'request') - .timestamp(timestamp) - .duration(1000) - .children( - ...(prev - ? [ - currentService - .span( - httpExitSpan({ - spanName: `exit-span-${currentService.fields['service.name']}`, - destinationUrl: `http://address-to-exit-span-${currentService.fields['service.name']}`, - }) - ) - .timestamp(timestamp) - .duration(1000) - .children(prev), - ] - : []) - ); + return withClient( + apmEsClient, + range.ratePerMinute(tracesPerMinute).generator((timestamp) => { + const rootTransaction = services.reduce((prev, currentService) => { + const tx = currentService + .transaction(`GET /my/function`, 'request') + .timestamp(timestamp) + .duration(1000) + .children( + ...(prev + ? [ + currentService + .span( + httpExitSpan({ + spanName: `exit-span-${currentService.fields['service.name']}`, + destinationUrl: `http://address-to-exit-span-${currentService.fields['service.name']}`, + }) + ) + .timestamp(timestamp) + .duration(1000) + .children(prev), + ] + : []) + ); - return tx; - }, undefined as Transaction | undefined); + return tx; + }, undefined as Transaction | undefined); - return rootTransaction!; - }); + return rootTransaction!; + }) + ); }, }; }; diff --git a/packages/kbn-apm-synthtrace/src/scenarios/services_without_transactions.ts b/packages/kbn-apm-synthtrace/src/scenarios/services_without_transactions.ts index c7d535028a1af..b06111d4b6026 100644 --- a/packages/kbn-apm-synthtrace/src/scenarios/services_without_transactions.ts +++ b/packages/kbn-apm-synthtrace/src/scenarios/services_without_transactions.ts @@ -8,12 +8,13 @@ import { apm, ApmFields } from '@kbn/apm-synthtrace-client'; import { Scenario } from '../cli/scenario'; import { getSynthtraceEnvironment } from '../lib/utils/get_synthtrace_environment'; +import { withClient } from '../lib/utils/with_client'; const ENVIRONMENT = getSynthtraceEnvironment(__filename); -const scenario: Scenario = async ({ logger, scenarioOpts }) => { +const scenario: Scenario = async () => { return { - generate: ({ range }) => { + generate: ({ range, clients: { apmEsClient } }) => { const withTx = apm .service('service-with-transactions', ENVIRONMENT, 'java') .instance('instance'); @@ -26,7 +27,7 @@ const scenario: Scenario = async ({ logger, scenarioOpts }) => { .service('service-with-app-metrics-only', ENVIRONMENT, 'java') .instance('instance'); - return range + const data = range .interval('1m') .rate(1) .generator((timestamp) => { @@ -45,6 +46,8 @@ const scenario: Scenario = async ({ logger, scenarioOpts }) => { .timestamp(timestamp), ]; }); + + return withClient(apmEsClient, data); }, }; }; diff --git a/packages/kbn-apm-synthtrace/src/scenarios/simple_logs.ts b/packages/kbn-apm-synthtrace/src/scenarios/simple_logs.ts new file mode 100644 index 0000000000000..18c1fc1c52550 --- /dev/null +++ b/packages/kbn-apm-synthtrace/src/scenarios/simple_logs.ts @@ -0,0 +1,74 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ +import { LogDocument, log, generateShortId, generateLongId } from '@kbn/apm-synthtrace-client'; +import { Scenario } from '../cli/scenario'; +import { withClient } from '../lib/utils/with_client'; + +const scenario: Scenario = async (runOptions) => { + return { + generate: ({ range, clients: { logsEsClient } }) => { + const { logger } = runOptions; + + // Logs Data logic + const MESSAGE_LOG_LEVELS = [ + { message: 'A simple log', level: 'info' }, + { message: 'Yet another debug log', level: 'debug' }, + { message: 'Error with certificate: "ca_trusted_fingerprint"', level: 'error' }, + ]; + const CLOUD_PROVIDERS = ['gcp', 'aws', 'azure']; + const CLOUD_REGION = ['eu-central-1', 'us-east-1', 'area-51']; + + const CLUSTER = [ + { clusterId: generateShortId(), clusterName: 'synth-cluster-1' }, + { clusterId: generateShortId(), clusterName: 'synth-cluster-2' }, + { clusterId: generateShortId(), clusterName: 'synth-cluster-3' }, + ]; + + const SERVICE_NAMES = Array(3) + .fill(null) + .map((_, idx) => `synth-service-${idx}`); + + const logs = range + .interval('1m') + .rate(1) + .generator((timestamp) => { + return Array(20) + .fill(0) + .map(() => { + const index = Math.floor(Math.random() * 3); + return log + .create() + .message(MESSAGE_LOG_LEVELS[index].message) + .logLevel(MESSAGE_LOG_LEVELS[index].level) + .service(SERVICE_NAMES[index]) + .defaults({ + 'trace.id': generateShortId(), + 'agent.name': 'synth-agent', + 'orchestrator.cluster.name': CLUSTER[index].clusterName, + 'orchestrator.cluster.id': CLUSTER[index].clusterId, + 'orchestrator.resource.id': generateShortId(), + 'cloud.provider': CLOUD_PROVIDERS[Math.floor(Math.random() * 3)], + 'cloud.region': CLOUD_REGION[index], + 'cloud.availability_zone': `${CLOUD_REGION[index]}a`, + 'cloud.project.id': generateShortId(), + 'cloud.instance.id': generateShortId(), + 'log.file.path': `/logs/${generateLongId()}/error.txt`, + }) + .timestamp(timestamp); + }); + }); + + return withClient( + logsEsClient, + logger.perf('generating_logs', () => logs) + ); + }, + }; +}; + +export default scenario; diff --git a/packages/kbn-apm-synthtrace/src/scenarios/simple_trace.ts b/packages/kbn-apm-synthtrace/src/scenarios/simple_trace.ts index 827cbfca46e79..26b0c1282d514 100644 --- a/packages/kbn-apm-synthtrace/src/scenarios/simple_trace.ts +++ b/packages/kbn-apm-synthtrace/src/scenarios/simple_trace.ts @@ -8,6 +8,7 @@ import { ApmFields, apm, Instance } from '@kbn/apm-synthtrace-client'; import { Scenario } from '../cli/scenario'; import { getSynthtraceEnvironment } from '../lib/utils/get_synthtrace_environment'; +import { withClient } from '../lib/utils/with_client'; const ENVIRONMENT = getSynthtraceEnvironment(__filename); @@ -16,7 +17,7 @@ const scenario: Scenario = async (runOptions) => { const { numServices = 3 } = runOptions.scenarioOpts || {}; return { - generate: ({ range }) => { + generate: ({ range, clients: { apmEsClient } }) => { const transactionName = '240rpm/75% 1000ms'; const successfulTimestamps = range.interval('1m').rate(180); @@ -83,8 +84,11 @@ const scenario: Scenario = async (runOptions) => { return [successfulTraceEvents, failedTraceEvents, metricsets]; }; - return logger.perf('generating_apm_events', () => - instances.flatMap((instance) => instanceSpans(instance)) + return withClient( + apmEsClient, + logger.perf('generating_apm_events', () => + instances.flatMap((instance) => instanceSpans(instance)) + ) ); }, }; diff --git a/packages/kbn-apm-synthtrace/src/scenarios/span_links.ts b/packages/kbn-apm-synthtrace/src/scenarios/span_links.ts index 60f63f80e3dec..08930a815ffdf 100644 --- a/packages/kbn-apm-synthtrace/src/scenarios/span_links.ts +++ b/packages/kbn-apm-synthtrace/src/scenarios/span_links.ts @@ -11,6 +11,7 @@ import { Readable } from 'stream'; import { apm, ApmFields, generateLongId, generateShortId } from '@kbn/apm-synthtrace-client'; import { Scenario } from '../cli/scenario'; import { getSynthtraceEnvironment } from '../lib/utils/get_synthtrace_environment'; +import { withClient } from '../lib/utils/with_client'; const ENVIRONMENT = getSynthtraceEnvironment(__filename); @@ -32,7 +33,7 @@ function getSpanLinksFromEvents(events: ApmFields[]) { const scenario: Scenario = async () => { return { - generate: ({ range }) => { + generate: ({ range, clients: { apmEsClient } }) => { const producerInternalOnlyInstance = apm .service({ name: 'producer-internal-only', environment: ENVIRONMENT, agentName: 'go' }) @@ -111,8 +112,9 @@ const scenario: Scenario = async () => { ); }); - return Readable.from( - Array.from(producerInternalOnlyEvents).concat(Array.from(consumerEvents)) + return withClient( + apmEsClient, + Readable.from(Array.from(producerInternalOnlyEvents).concat(Array.from(consumerEvents))) ); }, }; diff --git a/packages/kbn-check-mappings-update-cli/current_mappings.json b/packages/kbn-check-mappings-update-cli/current_mappings.json index d2fde2f5a10a8..603f0efd54a87 100644 --- a/packages/kbn-check-mappings-update-cli/current_mappings.json +++ b/packages/kbn-check-mappings-update-cli/current_mappings.json @@ -42,10 +42,6 @@ } } }, - "metrics-data-source": { - "dynamic": false, - "properties": {} - }, "url": { "dynamic": false, "properties": { @@ -1473,6 +1469,10 @@ } } }, + "metrics-data-source": { + "dynamic": false, + "properties": {} + }, "canvas-element": { "dynamic": false, "properties": { @@ -2168,6 +2168,9 @@ "interval": { "type": "keyword" }, + "timeout": { + "type": "short" + }, "ecs_mapping": { "dynamic": false, "properties": {} @@ -2216,6 +2219,9 @@ "interval": { "type": "text" }, + "timeout": { + "type": "short" + }, "platform": { "type": "keyword" }, @@ -2258,6 +2264,9 @@ "interval": { "type": "text" }, + "timeout": { + "type": "short" + }, "platform": { "type": "keyword" }, @@ -2679,50 +2688,6 @@ } } }, - "apm-telemetry": { - "dynamic": false, - "properties": {} - }, - "apm-server-schema": { - "properties": { - "schemaJson": { - "type": "text", - "index": false - } - } - }, - "apm-service-group": { - "properties": { - "groupName": { - "type": "keyword" - }, - "kuery": { - "type": "text" - }, - "description": { - "type": "text" - }, - "color": { - "type": "text" - } - } - }, - "apm-custom-dashboards": { - "properties": { - "dashboardSavedObjectId": { - "type": "keyword" - }, - "kuery": { - "type": "text" - }, - "serviceEnvironmentFilterEnabled": { - "type": "boolean" - }, - "serviceNameFilterEnabled": { - "type": "boolean" - } - } - }, "enterprise_search_telemetry": { "dynamic": false, "properties": {} @@ -3196,5 +3161,49 @@ "index": false } } + }, + "apm-telemetry": { + "dynamic": false, + "properties": {} + }, + "apm-server-schema": { + "properties": { + "schemaJson": { + "type": "text", + "index": false + } + } + }, + "apm-service-group": { + "properties": { + "groupName": { + "type": "keyword" + }, + "kuery": { + "type": "text" + }, + "description": { + "type": "text" + }, + "color": { + "type": "text" + } + } + }, + "apm-custom-dashboards": { + "properties": { + "dashboardSavedObjectId": { + "type": "keyword" + }, + "kuery": { + "type": "text" + }, + "serviceEnvironmentFilterEnabled": { + "type": "boolean" + }, + "serviceNameFilterEnabled": { + "type": "boolean" + } + } } } diff --git a/packages/kbn-doc-links/src/get_doc_links.ts b/packages/kbn-doc-links/src/get_doc_links.ts index 9e0d380c2f016..afc8252e7e13e 100644 --- a/packages/kbn-doc-links/src/get_doc_links.ts +++ b/packages/kbn-doc-links/src/get_doc_links.ts @@ -769,6 +769,7 @@ export const getDocLinks = ({ kibanaBranch }: GetDocLinkOptions): DocLinks => { uninstallAgent: `${SECURITY_SOLUTION_DOCS}uninstall-agent.html`, installAndUninstallIntegrationAssets: `${FLEET_DOCS}install-uninstall-integration-assets.html`, elasticAgentInputConfiguration: `${FLEET_DOCS}elastic-agent-input-configuration.html`, + policySecrets: `${FLEET_DOCS}agent-policy.html#agent-policy-secret-values`, }, ecs: { guide: `${ELASTIC_WEBSITE_URL}guide/en/ecs/current/index.html`, diff --git a/packages/kbn-doc-links/src/types.ts b/packages/kbn-doc-links/src/types.ts index 37974c9244b73..5e4202dd7fa45 100644 --- a/packages/kbn-doc-links/src/types.ts +++ b/packages/kbn-doc-links/src/types.ts @@ -527,6 +527,7 @@ export interface DocLinks { uninstallAgent: string; installAndUninstallIntegrationAssets: string; elasticAgentInputConfiguration: string; + policySecrets: string; }>; readonly ecs: { readonly guide: string; diff --git a/packages/kbn-expandable-flyout/README.md b/packages/kbn-expandable-flyout/README.md index 63a6f9483ead0..3e3b620a06b53 100644 --- a/packages/kbn-expandable-flyout/README.md +++ b/packages/kbn-expandable-flyout/README.md @@ -16,8 +16,12 @@ The flyout is composed of 3 sections: The expandable-flyout package is designed to render a single flyout for an entire plugin. While displaying multiple flyouts might be feasible, it will be a bit complicated, and we recommend instead to build multiple panels, with each their own context to manage their data (for example, take a look at the Security Solution [setup](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/flyout)). The expandable-flyout is making some strict UI design decisions: -- when in collapsed mode (i.e. when only the right/preview section is open), the flyout's width is fixed to the EUI `s` size -- when in expanded mode (i.e. when the left section is opened), the flyout's width is fixed to the EUI `l` size. Internally the right, left and preview sections' widths are set to a hardcoded percentage (40%, 60$ and 40% respectively) +- when in collapsed mode (i.e. when only the right/preview section is open), the flyout's width linearly grows from its minimum value of 380px to its maximum value of 750px +- when in expanded mode (i.e. when the left section is opened), the flyout's width changes depending on the browser's width: + - if the window is smaller than 1600px, the flyout takes the entire browser window (minus 48px of padding on the left) + - for windows bigger than 1600px, the flyout's width is 80% of the entire browser window (with a max width of 1500px for the left section, and 750px for the right section) + +> While the expandable-flyout will work on very small screens, having both the right and left sections visible at the same time will not be a good experience to the user. We recommend only showing the right panel, and therefore handling this situation when you build your panels by considering hiding the actions that could open the left panel (like the expand details button in the [FlyoutNavigation](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/flyout/shared/components/flyout_navigation.tsx)). ## Package API diff --git a/packages/kbn-expandable-flyout/src/components/left_section.tsx b/packages/kbn-expandable-flyout/src/components/left_section.tsx index 1d2a4a7eeabac..37cc0564d22ee 100644 --- a/packages/kbn-expandable-flyout/src/components/left_section.tsx +++ b/packages/kbn-expandable-flyout/src/components/left_section.tsx @@ -26,7 +26,7 @@ interface LeftSectionProps { */ export const LeftSection: React.FC = ({ component, width }: LeftSectionProps) => { const style = useMemo( - () => ({ height: '100%', width: `${width * 100}%` }), + () => ({ height: '100%', width: `${width}px` }), [width] ); return ( diff --git a/packages/kbn-expandable-flyout/src/components/preview_section.test.tsx b/packages/kbn-expandable-flyout/src/components/preview_section.test.tsx index f365c8f299623..950d406893082 100644 --- a/packages/kbn-expandable-flyout/src/components/preview_section.test.tsx +++ b/packages/kbn-expandable-flyout/src/components/preview_section.test.tsx @@ -8,10 +8,11 @@ import React from 'react'; import { render } from '@testing-library/react'; -import { PreviewSection } from './preview_section'; +import { PreviewBanner, PreviewSection } from './preview_section'; import { PREVIEW_SECTION_BACK_BUTTON_TEST_ID, PREVIEW_SECTION_CLOSE_BUTTON_TEST_ID, + PREVIEW_SECTION_TEST_ID, } from './test_ids'; import { ExpandableFlyoutContext } from '../context'; @@ -28,14 +29,15 @@ describe('PreviewSection', () => { }, } as unknown as ExpandableFlyoutContext; + const component =

{'component'}
; + const left = 500; + it('should render close button in header', () => { - const component =
{'component'}
; - const width = 500; const showBackButton = false; const { getByTestId } = render( - + ); @@ -43,16 +45,43 @@ describe('PreviewSection', () => { }); it('should render back button in header', () => { - const component =
{'component'}
; - const width = 500; const showBackButton = true; const { getByTestId } = render( - + ); expect(getByTestId(PREVIEW_SECTION_BACK_BUTTON_TEST_ID)).toBeInTheDocument(); }); + + it('should render banner', () => { + const showBackButton = false; + const title = 'test'; + const banner: PreviewBanner = { + title, + backgroundColor: 'primary', + textColor: 'red', + }; + + const { getByTestId, getByText } = render( + + + + ); + + expect(getByTestId(`${PREVIEW_SECTION_TEST_ID}BannerPanel`)).toHaveClass( + `euiPanel--${banner.backgroundColor}` + ); + expect(getByTestId(`${PREVIEW_SECTION_TEST_ID}BannerText`)).toHaveStyle( + `color: ${banner.textColor}` + ); + expect(getByText(title)).toBeInTheDocument(); + }); }); diff --git a/packages/kbn-expandable-flyout/src/components/preview_section.tsx b/packages/kbn-expandable-flyout/src/components/preview_section.tsx index 1cc2243d65849..ae96bdb7ce187 100644 --- a/packages/kbn-expandable-flyout/src/components/preview_section.tsx +++ b/packages/kbn-expandable-flyout/src/components/preview_section.tsx @@ -65,9 +65,9 @@ interface PreviewSectionProps { */ component: React.ReactElement; /** - * Width used when rendering the panel + * Left position used when rendering the panel */ - width: number; + leftPosition: number; /** * Display the back button in the header */ @@ -85,12 +85,13 @@ interface PreviewSectionProps { export const PreviewSection: React.FC = ({ component, showBackButton, - width, + leftPosition, banner, }: PreviewSectionProps) => { const { euiTheme } = useEuiTheme(); const { closePreviewPanel, previousPreviewPanel } = useExpandableFlyoutContext(); - const left = `${(1 - width) * 100}%`; + + const left = leftPosition + 4; const closeButton = ( @@ -103,7 +104,7 @@ export const PreviewSection: React.FC = ({ ); const header = showBackButton ? ( - + = ({ {closeButton} ) : ( - {closeButton} + + {closeButton} + ); return (
{isPreviewBanner(banner) && ( - - + + {banner.title} diff --git a/packages/kbn-expandable-flyout/src/components/right_section.tsx b/packages/kbn-expandable-flyout/src/components/right_section.tsx index 6e7e94dc14048..ae6cad5c7e9f3 100644 --- a/packages/kbn-expandable-flyout/src/components/right_section.tsx +++ b/packages/kbn-expandable-flyout/src/components/right_section.tsx @@ -29,7 +29,7 @@ export const RightSection: React.FC = ({ width, }: RightSectionProps) => { const style = useMemo( - () => ({ height: '100%', width: `${width * 100}%` }), + () => ({ height: '100%', width: `${width}px` }), [width] ); diff --git a/packages/kbn-expandable-flyout/src/hooks/use_sections_sizes.test.ts b/packages/kbn-expandable-flyout/src/hooks/use_sections_sizes.test.ts new file mode 100644 index 0000000000000..cc8f7e0f283ee --- /dev/null +++ b/packages/kbn-expandable-flyout/src/hooks/use_sections_sizes.test.ts @@ -0,0 +1,250 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may 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 { renderHook } from '@testing-library/react-hooks'; +import type { RenderHookResult } from '@testing-library/react-hooks'; +import type { UserSectionsSizesParams, UserSectionsSizesResult } from './use_sections_sizes'; +import { useSectionSizes } from './use_sections_sizes'; + +describe('useSectionSizes', () => { + let hookResult: RenderHookResult; + + describe('Right section', () => { + it('should return 0 for right section if it is hidden', () => { + const initialProps = { + windowWidth: 350, + showRight: false, + showLeft: false, + showPreview: false, + }; + hookResult = renderHook((props: UserSectionsSizesParams) => useSectionSizes(props), { + initialProps, + }); + + expect(hookResult.result.current).toEqual({ + rightSectionWidth: 0, + leftSectionWidth: 0, + flyoutWidth: '0px', + previewSectionLeft: 0, + }); + }); + + it('should return the window width for right section size for tiny screen', () => { + const initialProps = { + windowWidth: 350, + showRight: true, + showLeft: false, + showPreview: false, + }; + hookResult = renderHook((props: UserSectionsSizesParams) => useSectionSizes(props), { + initialProps, + }); + + expect(hookResult.result.current).toEqual({ + rightSectionWidth: 350, + leftSectionWidth: 0, + flyoutWidth: '350px', + previewSectionLeft: 0, + }); + }); + + it('should return 380 for right section size for medium screen', () => { + const initialProps = { + windowWidth: 600, + showRight: true, + showLeft: false, + showPreview: false, + }; + hookResult = renderHook((props: UserSectionsSizesParams) => useSectionSizes(props), { + initialProps, + }); + + expect(hookResult.result.current).toEqual({ + rightSectionWidth: 380, + leftSectionWidth: 0, + flyoutWidth: '380px', + previewSectionLeft: 0, + }); + }); + + it('should return 500 for right section size for large screen', () => { + const initialProps = { + windowWidth: 1300, + showRight: true, + showLeft: false, + showPreview: false, + }; + hookResult = renderHook((props: UserSectionsSizesParams) => useSectionSizes(props), { + initialProps, + }); + + expect(hookResult.result.current.rightSectionWidth).toBeGreaterThan(420); + expect(hookResult.result.current.rightSectionWidth).toBeLessThan(750); + expect(hookResult.result.current.leftSectionWidth).toEqual(0); + expect(hookResult.result.current.flyoutWidth).toEqual( + `${hookResult.result.current.rightSectionWidth}px` + ); + expect(hookResult.result.current.previewSectionLeft).toEqual(0); + }); + + it('should return 750 for right section size for very large screen', () => { + const initialProps = { + windowWidth: 2500, + showRight: true, + showLeft: false, + showPreview: false, + }; + hookResult = renderHook((props: UserSectionsSizesParams) => useSectionSizes(props), { + initialProps, + }); + + expect(hookResult.result.current).toEqual({ + rightSectionWidth: 750, + leftSectionWidth: 0, + flyoutWidth: '750px', + previewSectionLeft: 0, + }); + }); + }); + + describe('Left section', () => { + it('should return 0 for left section if it is hidden', () => { + const initialProps = { + windowWidth: 500, + showRight: true, + showLeft: false, + showPreview: false, + }; + hookResult = renderHook((props: UserSectionsSizesParams) => useSectionSizes(props), { + initialProps, + }); + + expect(hookResult.result.current).toEqual({ + rightSectionWidth: 380, + leftSectionWidth: 0, + flyoutWidth: '380px', + previewSectionLeft: 0, + }); + }); + + it('should return the remaining for left section', () => { + const initialProps = { + windowWidth: 500, + showRight: true, + showLeft: true, + showPreview: false, + }; + hookResult = renderHook((props: UserSectionsSizesParams) => useSectionSizes(props), { + initialProps, + }); + + expect(hookResult.result.current).toEqual({ + rightSectionWidth: 380, + leftSectionWidth: 72, + flyoutWidth: '452px', + previewSectionLeft: 0, + }); + }); + + it('should return 80% of remaining for left section', () => { + const initialProps = { + windowWidth: 2500, + showRight: true, + showLeft: true, + showPreview: false, + }; + hookResult = renderHook((props: UserSectionsSizesParams) => useSectionSizes(props), { + initialProps, + }); + + expect(hookResult.result.current.rightSectionWidth).toEqual(750); + expect(hookResult.result.current.leftSectionWidth).toEqual((2500 - 750) * 0.8); + expect(hookResult.result.current.flyoutWidth).toEqual( + `${ + hookResult.result.current.rightSectionWidth + hookResult.result.current.leftSectionWidth + }px` + ); + expect(hookResult.result.current.previewSectionLeft).toEqual(0); + }); + + it('should return max out at 1500px for really big screens', () => { + const initialProps = { + windowWidth: 2700, + showRight: true, + showLeft: true, + showPreview: false, + }; + hookResult = renderHook((props: UserSectionsSizesParams) => useSectionSizes(props), { + initialProps, + }); + + expect(hookResult.result.current.rightSectionWidth).toEqual(750); + expect(hookResult.result.current.leftSectionWidth).toEqual(1500); + expect(hookResult.result.current.flyoutWidth).toEqual( + `${ + hookResult.result.current.rightSectionWidth + hookResult.result.current.leftSectionWidth + }px` + ); + expect(hookResult.result.current.previewSectionLeft).toEqual(0); + }); + }); + + describe('Preview section', () => { + it('should return the 0 for preview section if it is hidden', () => { + const initialProps = { + windowWidth: 600, + showRight: true, + showLeft: false, + showPreview: false, + }; + hookResult = renderHook((props: UserSectionsSizesParams) => useSectionSizes(props), { + initialProps, + }); + + expect(hookResult.result.current).toEqual({ + rightSectionWidth: 380, + leftSectionWidth: 0, + flyoutWidth: '380px', + previewSectionLeft: 0, + }); + }); + + it('should return the 0 for preview section when left section is hidden', () => { + const initialProps = { + windowWidth: 600, + showRight: true, + showLeft: false, + showPreview: true, + }; + hookResult = renderHook((props: UserSectionsSizesParams) => useSectionSizes(props), { + initialProps, + }); + + expect(hookResult.result.current).toEqual({ + rightSectionWidth: 380, + leftSectionWidth: 0, + flyoutWidth: '380px', + previewSectionLeft: 0, + }); + }); + + it('should return for preview section when left section is visible', () => { + const initialProps = { windowWidth: 600, showRight: true, showLeft: true, showPreview: true }; + hookResult = renderHook((props: UserSectionsSizesParams) => useSectionSizes(props), { + initialProps, + }); + + expect(hookResult.result.current).toEqual({ + rightSectionWidth: 380, + leftSectionWidth: 172, + flyoutWidth: '552px', + previewSectionLeft: 172, + }); + }); + }); +}); diff --git a/packages/kbn-expandable-flyout/src/hooks/use_sections_sizes.ts b/packages/kbn-expandable-flyout/src/hooks/use_sections_sizes.ts new file mode 100644 index 0000000000000..94b10cde6e1c8 --- /dev/null +++ b/packages/kbn-expandable-flyout/src/hooks/use_sections_sizes.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 and the Server Side Public License, v 1; you may 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 RIGHT_SECTION_MIN_WIDTH = 380; +const MIN_RESOLUTION_BREAKPOINT = 992; +const RIGHT_SECTION_MAX_WIDTH = 750; +const MAX_RESOLUTION_BREAKPOINT = 1920; + +const LEFT_SECTION_MAX_WIDTH = 1500; + +const FULL_WIDTH_BREAKPOINT = 1600; +const FULL_WIDTH_PADDING = 48; + +export interface UserSectionsSizesParams { + /** + * The width of the browser window + */ + windowWidth: number; + /** + * True if the right section is visible, false otherwise + */ + showRight: boolean; + /** + * True if the left section is visible, false otherwise + */ + showLeft: boolean; + /** + * True if the preview section is visible, false otherwise + */ + showPreview: boolean; +} + +export interface UserSectionsSizesResult { + /** + * Width of the right section in pixels + */ + rightSectionWidth: number; + /** + * Width of the left section in pixels + */ + leftSectionWidth: number; + /** + * Width of the flyout in pixels + */ + flyoutWidth: string; + /** + * Left position of the preview section in pixels + */ + previewSectionLeft: number; +} + +/** + * Hook that calculate the different width for the sections of the flyout and the flyout itself + */ +export const useSectionSizes = ({ + windowWidth, + showRight, + showLeft, + showPreview, +}: UserSectionsSizesParams): UserSectionsSizesResult => { + let rightSectionWidth: number = 0; + if (showRight) { + if (windowWidth < MIN_RESOLUTION_BREAKPOINT) { + // the right section's width will grow from 380px (at 992px resolution) while handling tiny screens by not going smaller than the window width + rightSectionWidth = Math.min(RIGHT_SECTION_MIN_WIDTH, windowWidth); + } else { + const ratioWidth = + (RIGHT_SECTION_MAX_WIDTH - RIGHT_SECTION_MIN_WIDTH) * + ((windowWidth - MIN_RESOLUTION_BREAKPOINT) / + (MAX_RESOLUTION_BREAKPOINT - MIN_RESOLUTION_BREAKPOINT)); + + // the right section's width will grow to 750px (at 1920px resolution) and will never go bigger than 750px in higher resolutions + rightSectionWidth = Math.min(RIGHT_SECTION_MIN_WIDTH + ratioWidth, RIGHT_SECTION_MAX_WIDTH); + } + } + + let leftSectionWidth: number = 0; + if (showLeft) { + // the left section's width will be nearly the remaining space for resolution lower than 1600px + if (windowWidth <= FULL_WIDTH_BREAKPOINT) { + leftSectionWidth = windowWidth - rightSectionWidth - FULL_WIDTH_PADDING; + } else { + // the left section's width will be taking 80% of the remaining space for resolution higher than 1600px, while never going bigger than 1500px + leftSectionWidth = Math.min( + ((windowWidth - rightSectionWidth) * 80) / 100, + LEFT_SECTION_MAX_WIDTH + ); + } + } + + const flyoutWidth: string = + showRight && showLeft ? `${rightSectionWidth + leftSectionWidth}px` : `${rightSectionWidth}px`; + + // preview section's width should only be similar to the right section. + // Though because the preview is rendered with an absolute position in the flyout, we calculate its left position instead of the width + let previewSectionLeft: number = 0; + if (showPreview) { + // the preview section starts where the left section ends + previewSectionLeft = leftSectionWidth; + } + + return { + rightSectionWidth, + leftSectionWidth, + flyoutWidth, + previewSectionLeft, + }; +}; diff --git a/packages/kbn-expandable-flyout/src/hooks/use_window_size.test.ts b/packages/kbn-expandable-flyout/src/hooks/use_window_size.test.ts new file mode 100644 index 0000000000000..cb9f44d36e2fd --- /dev/null +++ b/packages/kbn-expandable-flyout/src/hooks/use_window_size.test.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 and the Server Side Public License, v 1; you may 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 { renderHook } from '@testing-library/react-hooks'; +import { useWindowSize } from './use_window_size'; + +describe('useWindowSize', () => { + it('should return the window size', () => { + const hookResult = renderHook(() => useWindowSize()); + expect(hookResult.result.current).toEqual(1024); + }); +}); diff --git a/packages/kbn-expandable-flyout/src/hooks/use_window_size.ts b/packages/kbn-expandable-flyout/src/hooks/use_window_size.ts new file mode 100644 index 0000000000000..0d773ad02c1c3 --- /dev/null +++ b/packages/kbn-expandable-flyout/src/hooks/use_window_size.ts @@ -0,0 +1,25 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { useLayoutEffect, useState } from 'react'; + +/** + * Hook that returns the browser window width + */ +export const useWindowSize = (): number => { + const [width, setWidth] = useState(0); + useLayoutEffect(() => { + function updateSize() { + setWidth(window.innerWidth); + } + window.addEventListener('resize', updateSize); + updateSize(); + return () => window.removeEventListener('resize', updateSize); + }, []); + return width; +}; diff --git a/packages/kbn-expandable-flyout/src/index.tsx b/packages/kbn-expandable-flyout/src/index.tsx index d5a1bff46439b..17613be6859b7 100644 --- a/packages/kbn-expandable-flyout/src/index.tsx +++ b/packages/kbn-expandable-flyout/src/index.tsx @@ -7,8 +7,10 @@ */ import React, { useCallback, useMemo } from 'react'; -import type { EuiFlyoutProps } from '@elastic/eui'; +import { EuiFlyoutProps } from '@elastic/eui'; import { EuiFlexGroup, EuiFlyout } from '@elastic/eui'; +import { useSectionSizes } from './hooks/use_sections_sizes'; +import { useWindowSize } from './hooks/use_window_size'; import { useExpandableFlyoutContext } from './context'; import { PreviewSection } from './components/preview_section'; import { RightSection } from './components/right_section'; @@ -16,6 +18,8 @@ import type { FlyoutPanelProps, Panel } from './types'; import { LeftSection } from './components/left_section'; import { isPreviewBanner } from './components/preview_section'; +const flyoutInnerStyles = { height: '100%' }; + export interface ExpandableFlyoutProps extends Omit { /** * List of all registered panels available for render @@ -27,8 +31,6 @@ export interface ExpandableFlyoutProps extends Omit { handleOnFlyoutClosed?: () => void; } -const flyoutInnerStyles = { height: '100%' }; - /** * Expandable flyout UI React component. * Displays 3 sections (right, left, preview) depending on the panels in the context. @@ -41,6 +43,8 @@ export const ExpandableFlyout: React.FC = ({ handleOnFlyoutClosed, ...flyoutProps }) => { + const windowWidth = useWindowSize(); + const { panels, closeFlyout } = useExpandableFlyoutContext(); const { left, right, preview } = panels; @@ -71,17 +75,22 @@ export const ExpandableFlyout: React.FC = ({ [mostRecentPreview, registeredPanels] ); - const hideFlyout = !left && !right && !preview.length; + const showRight = rightSection != null && right != null; + const showLeft = leftSection != null && left != null; + const showPreview = previewSection != null && preview != null; + + const { rightSectionWidth, leftSectionWidth, flyoutWidth, previewSectionLeft } = useSectionSizes({ + windowWidth, + showRight, + showLeft, + showPreview, + }); + const hideFlyout = !left && !right && !preview.length; if (hideFlyout) { return null; } - const flyoutWidth: string = leftSection && rightSection ? 'l' : 's'; - const rightSectionWidth: number = leftSection ? 0.4 : 1; - const leftSectionWidth: number = 0.6; - const previewSectionWidth: number = leftSection ? 0.4 : 1; - return ( = ({ wrap={false} gutterSize="none" style={flyoutInnerStyles} + responsive={false} > - {leftSection && left ? ( + {showLeft ? ( ) : null} - {rightSection && right ? ( + {showRight ? ( = ({ ) : null} - {previewSection && preview ? ( + {showPreview ? ( ) : null} diff --git a/packages/kbn-generate-csv-types/README.md b/packages/kbn-generate-csv-types/README.md deleted file mode 100644 index 9046a9264ea6b..0000000000000 --- a/packages/kbn-generate-csv-types/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# @kbn/generate-csv-types - -This package includes interfaces specific to the @kbn/generate-csv package. \ No newline at end of file diff --git a/packages/kbn-generate-csv/kibana.jsonc b/packages/kbn-generate-csv/kibana.jsonc index 9769151714f2a..d29b33047007c 100644 --- a/packages/kbn-generate-csv/kibana.jsonc +++ b/packages/kbn-generate-csv/kibana.jsonc @@ -1,5 +1,5 @@ { - "type": "shared-common", + "type": "shared-server", "id": "@kbn/generate-csv", "owner": "@elastic/appex-sharedux" } diff --git a/packages/kbn-generate-csv/src/constants.ts b/packages/kbn-generate-csv/src/constants.ts index cdaadf7451e37..aa4fb3f1b4980 100644 --- a/packages/kbn-generate-csv/src/constants.ts +++ b/packages/kbn-generate-csv/src/constants.ts @@ -10,3 +10,5 @@ export const CSV_BOM_CHARS = '\ufeff'; export const CONTENT_TYPE_CSV = 'text/csv'; export const UI_SETTINGS_CSV_SEPARATOR = 'csv:separator'; export const UI_SETTINGS_CSV_QUOTE_VALUES = 'csv:quoteValues'; +export const UI_SETTINGS_SEARCH_INCLUDE_FROZEN = 'search:includeFrozen'; +export const UI_SETTINGS_DATEFORMAT_TZ = 'dateFormat:tz'; diff --git a/packages/kbn-generate-csv/src/generate_csv.test.ts b/packages/kbn-generate-csv/src/generate_csv.test.ts index 52f15d6a82c49..22857f37afdaf 100644 --- a/packages/kbn-generate-csv/src/generate_csv.test.ts +++ b/packages/kbn-generate-csv/src/generate_csv.test.ts @@ -6,6 +6,10 @@ * Side Public License, v 1. */ +import { identity, range } from 'lodash'; +import * as Rx from 'rxjs'; +import type { Writable } from 'stream'; + import { errors as esErrors, estypes } from '@elastic/elasticsearch'; import type { SearchResponse } from '@elastic/elasticsearch/lib/api/types'; import type { IScopedClusterClient, IUiSettingsClient, Logger } from '@kbn/core/server'; @@ -20,22 +24,24 @@ import { searchSourceInstanceMock } from '@kbn/data-plugin/common/search/search_ import { IScopedSearchClient } from '@kbn/data-plugin/server'; import { dataPluginMock } from '@kbn/data-plugin/server/mocks'; import { FieldFormatsRegistry } from '@kbn/field-formats-plugin/common'; -import { identity, range } from 'lodash'; -import * as Rx from 'rxjs'; -import type { Writable } from 'stream'; +import { CancellationToken } from '@kbn/reporting-common'; +import type { ReportingConfigType } from '@kbn/reporting-server'; +import { JobParamsCSV } from '@kbn/reporting-export-types-csv-common'; +import { + UI_SETTINGS_CSV_QUOTE_VALUES, + UI_SETTINGS_CSV_SEPARATOR, + UI_SETTINGS_DATEFORMAT_TZ, +} from './constants'; import { CsvGenerator } from './generate_csv'; -import { CancellationToken, UI_SETTINGS_DATEFORMAT_TZ } from '@kbn/reporting-common'; -import { CsvConfig, JobParams } from '@kbn/generate-csv-types'; -import { UI_SETTINGS_CSV_QUOTE_VALUES, UI_SETTINGS_CSV_SEPARATOR } from './constants'; -const createMockJob = (baseObj: any = {}): JobParams => ({ +const createMockJob = (baseObj: any = {}): JobParamsCSV => ({ ...baseObj, }); describe('CsvGenerator', () => { let mockEsClient: IScopedClusterClient; let mockDataClient: IScopedSearchClient; - let mockConfig: CsvConfig; + let mockConfig: ReportingConfigType['csv']; let mockLogger: jest.Mocked; let uiSettingsClient: IUiSettingsClient; let stream: jest.Mocked; @@ -111,6 +117,7 @@ describe('CsvGenerator', () => { maxSizeBytes: 180000, useByteOrderMarkEncoding: false, scroll: { size: 500, duration: '30s' }, + enablePanelActionDownload: true, }; searchSourceMock.getField = jest.fn((key: string) => { @@ -237,6 +244,7 @@ describe('CsvGenerator', () => { maxSizeBytes: TEST_MAX_SIZE, useByteOrderMarkEncoding: false, scroll: { size: 500, duration: '30s' }, + enablePanelActionDownload: true, }; mockDataClient.search = jest.fn().mockImplementation(() => @@ -750,6 +758,7 @@ describe('CsvGenerator', () => { maxSizeBytes: 180000, useByteOrderMarkEncoding: false, scroll: { size: 500, duration: '30s' }, + enablePanelActionDownload: true, }; mockDataClient.search = jest.fn().mockImplementation(() => Rx.of({ diff --git a/packages/kbn-generate-csv/src/generate_csv.ts b/packages/kbn-generate-csv/src/generate_csv.ts index 9d3b85b214c94..59e69e9989c8e 100644 --- a/packages/kbn-generate-csv/src/generate_csv.ts +++ b/packages/kbn-generate-csv/src/generate_csv.ts @@ -6,10 +6,13 @@ * Side Public License, v 1. */ +import { lastValueFrom } from 'rxjs'; +import type { Writable } from 'stream'; + import { errors as esErrors, estypes } from '@elastic/elasticsearch'; import type { IScopedClusterClient, IUiSettingsClient, Logger } from '@kbn/core/server'; import type { ISearchSource, ISearchStartSearchSource } from '@kbn/data-plugin/common'; -import { cellHasFormulas, ES_SEARCH_STRATEGY, tabifyDocs } from '@kbn/data-plugin/common'; +import { ES_SEARCH_STRATEGY, cellHasFormulas, tabifyDocs } from '@kbn/data-plugin/common'; import type { IScopedSearchClient } from '@kbn/data-plugin/server'; import type { Datatable } from '@kbn/expressions-plugin/server'; import type { @@ -17,20 +20,20 @@ import type { FieldFormatConfig, IFieldFormatsRegistry, } from '@kbn/field-formats-plugin/common'; -import { lastValueFrom } from 'rxjs'; -import type { Writable } from 'stream'; import { - CancellationToken, AuthenticationExpiredError, + CancellationToken, ReportingError, - TaskRunResult, byteSizeValueToNumber, } from '@kbn/reporting-common'; -import { CsvConfig, JobParams } from '@kbn/generate-csv-types'; -import { MaxSizeStringBuilder } from './max_size_string_builder'; -import { i18nTexts } from './i18n_texts'; -import { CsvExportSettings, getExportSettings } from './get_export_settings'; +import type { TaskRunResult } from '@kbn/reporting-common/types'; +import type { ReportingConfigType } from '@kbn/reporting-server'; + import { CONTENT_TYPE_CSV } from './constants'; +import { CsvExportSettings, getExportSettings } from './get_export_settings'; +import { i18nTexts } from './i18n_texts'; +import { MaxSizeStringBuilder } from './max_size_string_builder'; +import { JobParamsCSV } from '../types'; interface Clients { es: IScopedClusterClient; @@ -49,8 +52,8 @@ export class CsvGenerator { private csvRowCount = 0; constructor( - private job: Omit, - private config: CsvConfig, + private job: Omit, + private config: ReportingConfigType['csv'], private clients: Clients, private dependencies: Dependencies, private cancellationToken: CancellationToken, diff --git a/packages/kbn-generate-csv/src/get_export_settings.test.ts b/packages/kbn-generate-csv/src/get_export_settings.test.ts index 4afbeeabcdaa5..18b2525cf7942 100644 --- a/packages/kbn-generate-csv/src/get_export_settings.test.ts +++ b/packages/kbn-generate-csv/src/get_export_settings.test.ts @@ -6,28 +6,31 @@ * Side Public License, v 1. */ -import { - UI_SETTINGS_SEARCH_INCLUDE_FROZEN, - UI_SETTINGS_DATEFORMAT_TZ, -} from '@kbn/reporting-common'; -import { IUiSettingsClient } from '@kbn/core/server'; +import type { IUiSettingsClient } from '@kbn/core/server'; import { loggingSystemMock, savedObjectsClientMock, uiSettingsServiceMock, } from '@kbn/core/server/mocks'; +import type { ReportingConfigType } from '@kbn/reporting-server'; + +import { + UI_SETTINGS_CSV_QUOTE_VALUES, + UI_SETTINGS_CSV_SEPARATOR, + UI_SETTINGS_DATEFORMAT_TZ, + UI_SETTINGS_SEARCH_INCLUDE_FROZEN, +} from './constants'; import { getExportSettings } from './get_export_settings'; -import { CsvConfig } from '@kbn/generate-csv-types'; -import { UI_SETTINGS_CSV_QUOTE_VALUES, UI_SETTINGS_CSV_SEPARATOR } from './constants'; describe('getExportSettings', () => { let uiSettingsClient: IUiSettingsClient; - const config: CsvConfig = { + const config: ReportingConfigType['csv'] = { checkForFormulas: true, escapeFormulaValues: false, maxSizeBytes: 180000, scroll: { size: 500, duration: '30s' }, useByteOrderMarkEncoding: false, + enablePanelActionDownload: true, }; const logger = loggingSystemMock.createLogger(); diff --git a/packages/kbn-generate-csv/src/get_export_settings.ts b/packages/kbn-generate-csv/src/get_export_settings.ts index 46d31afaf9e4f..faef6fdc60f87 100644 --- a/packages/kbn-generate-csv/src/get_export_settings.ts +++ b/packages/kbn-generate-csv/src/get_export_settings.ts @@ -6,18 +6,16 @@ * Side Public License, v 1. */ -import { ByteSizeValue } from '@kbn/config-schema'; +import type { ByteSizeValue } from '@kbn/config-schema'; import type { IUiSettingsClient, Logger } from '@kbn/core/server'; import { createEscapeValue } from '@kbn/data-plugin/common'; -import { CsvConfig } from '@kbn/generate-csv-types'; -import { - UI_SETTINGS_DATEFORMAT_TZ, - UI_SETTINGS_SEARCH_INCLUDE_FROZEN, -} from '@kbn/reporting-common'; +import type { ReportingConfigType } from '@kbn/reporting-server'; import { CSV_BOM_CHARS, UI_SETTINGS_CSV_QUOTE_VALUES, UI_SETTINGS_CSV_SEPARATOR, + UI_SETTINGS_DATEFORMAT_TZ, + UI_SETTINGS_SEARCH_INCLUDE_FROZEN, } from './constants'; export interface CsvExportSettings { @@ -37,7 +35,7 @@ export interface CsvExportSettings { export const getExportSettings = async ( client: IUiSettingsClient, - config: CsvConfig, + config: ReportingConfigType['csv'], timezone: string | undefined, logger: Logger ): Promise => { diff --git a/packages/kbn-generate-csv/tsconfig.json b/packages/kbn-generate-csv/tsconfig.json index e09d9a392772e..51dbd54dda73e 100644 --- a/packages/kbn-generate-csv/tsconfig.json +++ b/packages/kbn-generate-csv/tsconfig.json @@ -21,9 +21,10 @@ "@kbn/data-plugin", "@kbn/expressions-plugin", "@kbn/field-formats-plugin", - "@kbn/reporting-common", "@kbn/config-schema", "@kbn/i18n", - "@kbn/generate-csv-types", + "@kbn/reporting-common", + "@kbn/reporting-server", + "@kbn/reporting-export-types-csv-common", ] } diff --git a/packages/kbn-generate-csv-types/index.ts b/packages/kbn-generate-csv/types.ts similarity index 63% rename from packages/kbn-generate-csv-types/index.ts rename to packages/kbn-generate-csv/types.ts index 865ac302e06b9..6d7461609afe2 100644 --- a/packages/kbn-generate-csv-types/index.ts +++ b/packages/kbn-generate-csv/types.ts @@ -6,22 +6,13 @@ * Side Public License, v 1. */ -import { ByteSizeValue } from '@kbn/config-schema'; import type { SerializedSearchSourceFields } from '@kbn/data-plugin/public'; -export interface JobParams { +/** + * Duplicated from @kbn/reporting-export-types-csv-common to reduce dependencies + */ +export interface JobParamsCSV { + browserTimezone?: string; searchSource: SerializedSearchSourceFields; columns?: string[]; - browserTimezone?: string; -} - -export interface CsvConfig { - checkForFormulas: boolean; - escapeFormulaValues: boolean; - maxSizeBytes: number | ByteSizeValue; - useByteOrderMarkEncoding: boolean; - scroll: { - duration: string; - size: number; - }; } diff --git a/packages/kbn-lens-embeddable-utils/attribute_builder/types.ts b/packages/kbn-lens-embeddable-utils/attribute_builder/types.ts index 6c9011b9782dc..428f6aacce133 100644 --- a/packages/kbn-lens-embeddable-utils/attribute_builder/types.ts +++ b/packages/kbn-lens-embeddable-utils/attribute_builder/types.ts @@ -16,6 +16,7 @@ import type { XYState, FormulaPublicApi, XYLayerConfig, + FillStyle, } from '@kbn/lens-plugin/public'; export type LensAttributes = TypedLensByValueInput['attributes']; @@ -87,5 +88,6 @@ export type FormulaValueConfig = Omit & { export type StaticValueConfig = Omit & { color?: string; + fill?: FillStyle; value: string; }; diff --git a/packages/kbn-lens-embeddable-utils/attribute_builder/utils.ts b/packages/kbn-lens-embeddable-utils/attribute_builder/utils.ts index ed75956cadbe1..58981aab8bcb4 100644 --- a/packages/kbn-lens-embeddable-utils/attribute_builder/utils.ts +++ b/packages/kbn-lens-embeddable-utils/attribute_builder/utils.ts @@ -27,7 +27,7 @@ export type DateHistogramColumnParams = DateHistogramIndexPatternColumn['params' export type TopValuesColumnParams = Pick< TermsIndexPatternColumn['params'], - 'size' | 'orderDirection' | 'orderBy' + 'size' | 'orderDirection' | 'orderBy' | 'secondaryFields' | 'accuracyMode' >; export const getHistogramColumn = ({ @@ -37,10 +37,11 @@ export const getHistogramColumn = ({ columnName: string; options?: Partial< Pick & { - params: DateHistogramColumnParams; + params: Partial; } >; }) => { + const { interval = 'auto', ...rest } = options?.params ?? {}; return { [columnName]: { dataType: 'date', @@ -48,9 +49,8 @@ export const getHistogramColumn = ({ label: '@timestamp', operationType: 'date_histogram', scale: 'interval', - sourceField: '@timestamp', - ...options, - params: { interval: 'auto', ...options?.params }, + sourceField: options?.sourceField ?? '@timestamp', + params: { interval, ...rest }, } as DateHistogramIndexPatternColumn, }; }; diff --git a/packages/kbn-lens-embeddable-utils/attribute_builder/visualization_types/layers/xy_data_layer.ts b/packages/kbn-lens-embeddable-utils/attribute_builder/visualization_types/layers/xy_data_layer.ts index 21fe17d156cac..f4845a5c93ab9 100644 --- a/packages/kbn-lens-embeddable-utils/attribute_builder/visualization_types/layers/xy_data_layer.ts +++ b/packages/kbn-lens-embeddable-utils/attribute_builder/visualization_types/layers/xy_data_layer.ts @@ -86,7 +86,9 @@ export class XYDataLayer implements ChartLayer { ? getHistogramColumn({ columnName: HISTOGRAM_COLUMN_NAME, options: { - ...options.buckets.params, + params: { + ...options.buckets.params, + }, sourceField: options.buckets.field ?? dataView.timeFieldName, }, }) diff --git a/packages/kbn-lens-embeddable-utils/attribute_builder/visualization_types/layers/xy_reference_lines_layer.ts b/packages/kbn-lens-embeddable-utils/attribute_builder/visualization_types/layers/xy_reference_lines_layer.ts index 1823de59684e2..2a105c10677af 100644 --- a/packages/kbn-lens-embeddable-utils/attribute_builder/visualization_types/layers/xy_reference_lines_layer.ts +++ b/packages/kbn-lens-embeddable-utils/attribute_builder/visualization_types/layers/xy_reference_lines_layer.ts @@ -60,6 +60,7 @@ export class XYReferenceLinesLayer implements ChartLayer { @@ -80,6 +83,8 @@ export class XYChart implements Chart { endValue: this.chartConfig.visualOptions?.endValues, curveType: this.chartConfig.visualOptions?.lineInterpolation, emphasizeFitting: !this.chartConfig.visualOptions?.showDottedLine, + valueLabels: this.chartConfig.visualOptions?.valueLabels, + axisTitlesVisibilitySettings: this.chartConfig.visualOptions?.axisTitlesVisibilitySettings, }; } diff --git a/packages/kbn-lens-embeddable-utils/tsconfig.json b/packages/kbn-lens-embeddable-utils/tsconfig.json index eca0b277bff1d..6238ba09d0374 100644 --- a/packages/kbn-lens-embeddable-utils/tsconfig.json +++ b/packages/kbn-lens-embeddable-utils/tsconfig.json @@ -6,5 +6,11 @@ }, "include": ["**/*.ts"], "exclude": ["target/**/*"], - "kbn_references": ["@kbn/core", "@kbn/data-plugin", "@kbn/data-views-plugin", "@kbn/lens-plugin"] + "kbn_references": [ + "@kbn/core", + "@kbn/data-plugin", + "@kbn/data-views-plugin", + "@kbn/lens-plugin", + "@kbn/visualizations-plugin", + ] } diff --git a/packages/kbn-management/settings/application/__stories__/application.stories.tsx b/packages/kbn-management/settings/application/__stories__/application.stories.tsx index b7742e8eca541..efc27f7f8300c 100644 --- a/packages/kbn-management/settings/application/__stories__/application.stories.tsx +++ b/packages/kbn-management/settings/application/__stories__/application.stories.tsx @@ -40,6 +40,13 @@ export const SettingsApplication: Story = () => { showReloadPagePrompt={action('showReloadPagePrompt')} subscribeToUpdates={() => new Subscription()} addUrlToHistory={action('addUrlToHistory')} + validateChange={async (key, value) => { + action(`validateChange`)({ + key, + value, + }); + return { successfulValidation: true, valid: true }; + }} > diff --git a/packages/kbn-management/settings/application/services.tsx b/packages/kbn-management/settings/application/services.tsx index 09ce0780b06d4..d64657525d351 100644 --- a/packages/kbn-management/settings/application/services.tsx +++ b/packages/kbn-management/settings/application/services.tsx @@ -32,7 +32,10 @@ export type SettingsApplicationServices = Services & FormServices; export interface KibanaDependencies { settings: { - client: Pick; + client: Pick< + IUiSettingsClient, + 'getAll' | 'isCustom' | 'isOverridden' | 'getUpdate$' | 'validateValue' + >; }; history: ScopedHistory; } @@ -52,6 +55,7 @@ export const SettingsApplicationProvider: FC = ({ const { saveChanges, showError, + validateChange, showReloadPagePrompt, links, showDanger, @@ -72,7 +76,9 @@ export const SettingsApplicationProvider: FC = ({ addUrlToHistory, }} > - + {children} diff --git a/packages/kbn-management/settings/components/field_category/__stories__/categories.stories.tsx b/packages/kbn-management/settings/components/field_category/__stories__/categories.stories.tsx index 1a9fb03b27532..8185310c71a01 100644 --- a/packages/kbn-management/settings/components/field_category/__stories__/categories.stories.tsx +++ b/packages/kbn-management/settings/components/field_category/__stories__/categories.stories.tsx @@ -53,6 +53,13 @@ export const Categories: Story = (params) => { { + action(`validateChange`)({ + key, + value, + }); + return { successfulValidation: true, valid: true }; + }} > { + action(`validateChange`)({ + key, + value, + }); + return { successfulValidation: true, valid: true }; + }} {...{ isSavingEnabled, onFieldChange }} > diff --git a/packages/kbn-management/settings/components/field_input/__stories__/common.tsx b/packages/kbn-management/settings/components/field_input/__stories__/common.tsx index 39daed80f40b8..0bdd569b99749 100644 --- a/packages/kbn-management/settings/components/field_input/__stories__/common.tsx +++ b/packages/kbn-management/settings/components/field_input/__stories__/common.tsx @@ -75,7 +75,16 @@ export const getStory = (title: string, description: string) => }, decorators: [ (Story) => ( - + { + action(`validateChange`)({ + key, + value, + }); + return { successfulValidation: true, valid: true }; + }} + > diff --git a/packages/kbn-management/settings/components/field_input/input/array_input.test.tsx b/packages/kbn-management/settings/components/field_input/input/array_input.test.tsx index c954035e9c639..ee0d7cb5e723c 100644 --- a/packages/kbn-management/settings/components/field_input/input/array_input.test.tsx +++ b/packages/kbn-management/settings/components/field_input/input/array_input.test.tsx @@ -6,8 +6,7 @@ * Side Public License, v 1. */ import React from 'react'; -import { act, fireEvent, render, screen } from '@testing-library/react'; -import userEvent from '@testing-library/user-event'; +import { fireEvent, render, screen, waitFor } from '@testing-library/react'; import { ArrayInput } from './array_input'; import { TEST_SUBJ_PREFIX_FIELD } from '.'; @@ -60,34 +59,17 @@ describe('ArrayInput', () => { expect(screen.getByTestId(`${TEST_SUBJ_PREFIX_FIELD}-${id}`)).toHaveValue('foo, bar, baz'); }); - it('formats array when blurred', () => { + it('calls the onInputChange prop when the value changes', async () => { render(wrap()); const input = screen.getByTestId(`${TEST_SUBJ_PREFIX_FIELD}-${id}`); - fireEvent.focus(input); - userEvent.type(input, ',baz'); - expect(input).toHaveValue('foo, bar,baz'); - input.blur(); - expect(input).toHaveValue('foo, bar, baz'); - }); - - it('only calls onInputChange when blurred ', () => { - render(wrap()); - const input = screen.getByTestId(`${TEST_SUBJ_PREFIX_FIELD}-${id}`); - - fireEvent.focus(input); - userEvent.type(input, ',baz'); + fireEvent.change(input, { target: { value: 'foo, bar,baz' } }); - expect(input).toHaveValue('foo, bar,baz'); - expect(defaultProps.onInputChange).not.toHaveBeenCalled(); - - act(() => { - input.blur(); - }); - - expect(defaultProps.onInputChange).toHaveBeenCalledWith({ - type: 'array', - unsavedValue: ['foo', 'bar', 'baz'], - }); + await waitFor(() => + expect(defaultProps.onInputChange).toHaveBeenCalledWith({ + type: 'array', + unsavedValue: ['foo', 'bar', 'baz'], + }) + ); }); it('disables the input when isDisabled prop is true', () => { diff --git a/packages/kbn-management/settings/components/field_input/input/array_input.tsx b/packages/kbn-management/settings/components/field_input/input/array_input.tsx index f2ce42051eb04..0dc9b8ddc406e 100644 --- a/packages/kbn-management/settings/components/field_input/input/array_input.tsx +++ b/packages/kbn-management/settings/components/field_input/input/array_input.tsx @@ -6,12 +6,14 @@ * Side Public License, v 1. */ -import React, { useEffect, useState } from 'react'; +import React, { useCallback, useEffect, useMemo, useState } from 'react'; import { EuiFieldText, EuiFieldTextProps } from '@elastic/eui'; import { getFieldInputValue } from '@kbn/management-settings-utilities'; import { useUpdate } from '@kbn/management-settings-utilities'; +import { debounce } from 'lodash'; +import { useServices } from '../services'; import { InputProps } from '../types'; import { TEST_SUBJ_PREFIX_FIELD } from '.'; @@ -33,29 +35,45 @@ export const ArrayInput = ({ }: ArrayInputProps) => { const [inputValue] = getFieldInputValue(field, unsavedChange) || []; const [value, setValue] = useState(inputValue?.join(', ')); + const { validateChange } = useServices(); + const onUpdate = useUpdate({ onInputChange, field }); + + const updateValue = useCallback( + async (newValue: string, onUpdateFn) => { + const parsedValue = newValue + .replace(REGEX, ',') + .split(',') + .filter((v) => v !== ''); + const validationResponse = await validateChange(field.id, parsedValue); + if (validationResponse.successfulValidation && !validationResponse.valid) { + onUpdateFn({ + type: field.type, + unsavedValue: parsedValue, + isInvalid: !validationResponse.valid, + error: validationResponse.errorMessage, + }); + } else { + onUpdateFn({ type: field.type, unsavedValue: parsedValue }); + } + }, + [validateChange, field.id, field.type] + ); + + const debouncedUpdateValue = useMemo(() => { + // Trigger update 1000 ms after the user stopped typing to reduce validation requests to the server + return debounce(updateValue, 1000); + }, [updateValue]); - const onChange: EuiFieldTextProps['onChange'] = (event) => { + const onChange: EuiFieldTextProps['onChange'] = async (event) => { const newValue = event.target.value; setValue(newValue); + await debouncedUpdateValue(newValue, onUpdate); }; - const onUpdate = useUpdate({ onInputChange, field }); - useEffect(() => { setValue(inputValue?.join(', ')); }, [inputValue]); - // In the past, each keypress would invoke the `onChange` callback. This - // is likely wasteful, so we've switched it to `onBlur` instead. - const onBlur = (event: React.ChangeEvent) => { - const blurValue = event.target.value - .replace(REGEX, ',') - .split(',') - .filter((v) => v !== ''); - onUpdate({ type: field.type, unsavedValue: blurValue }); - setValue(blurValue.join(', ')); - }; - const { id, name, ariaAttributes } = field; const { ariaLabel, ariaDescribedBy } = ariaAttributes; @@ -66,7 +84,7 @@ export const ArrayInput = ({ disabled={!isSavingEnabled} aria-label={ariaLabel} aria-describedby={ariaDescribedBy} - {...{ name, onBlur, onChange, value }} + {...{ name, onChange, value }} /> ); }; diff --git a/packages/kbn-management/settings/components/field_input/input/code_editor_input.tsx b/packages/kbn-management/settings/components/field_input/input/code_editor_input.tsx index 5b9d90154d087..cbf53979efa83 100644 --- a/packages/kbn-management/settings/components/field_input/input/code_editor_input.tsx +++ b/packages/kbn-management/settings/components/field_input/input/code_editor_input.tsx @@ -6,13 +6,13 @@ * Side Public License, v 1. */ -import React from 'react'; - -import { i18n } from '@kbn/i18n'; +import React, { useCallback, useEffect, useMemo, useState } from 'react'; import { SettingType } from '@kbn/management-settings-types'; import { getFieldInputValue, useUpdate } from '@kbn/management-settings-utilities'; +import { debounce } from 'lodash'; +import { useServices } from '../services'; import { CodeEditor, CodeEditorProps } from '../code_editor'; import type { InputProps } from '../types'; import { TEST_SUBJ_PREFIX_FIELD } from '.'; @@ -45,39 +45,48 @@ export const CodeEditorInput = ({ defaultValue, onInputChange, }: CodeEditorInputProps) => { + // @ts-expect-error + const [inputValue] = getFieldInputValue(field, unsavedChange); + const [value, setValue] = useState(inputValue); + const { validateChange } = useServices(); const onUpdate = useUpdate({ onInputChange, field }); - const onChange: CodeEditorProps['onChange'] = (inputValue) => { - let newUnsavedValue; - let errorParams = {}; - - switch (type) { - case 'json': - const isJsonArray = Array.isArray(JSON.parse(defaultValue || '{}')); - newUnsavedValue = inputValue || (isJsonArray ? '[]' : '{}'); + const updateValue = useCallback( + async (newValue: string, onUpdateFn) => { + const isJsonArray = Array.isArray(JSON.parse(defaultValue || '{}')); + const parsedValue = newValue || (isJsonArray ? '[]' : '{}'); + const validationResponse = await validateChange(field.id, parsedValue); + if (validationResponse.successfulValidation && !validationResponse.valid) { + onUpdateFn({ + type: field.type, + unsavedValue: newValue, + isInvalid: !validationResponse.valid, + error: validationResponse.errorMessage, + }); + } else { + onUpdateFn({ type: field.type, unsavedValue: newValue }); + } + }, + [validateChange, field.id, field.type, defaultValue] + ); - try { - JSON.parse(newUnsavedValue); - } catch (e) { - errorParams = { - error: i18n.translate('management.settings.field.codeEditorSyntaxErrorMessage', { - defaultMessage: 'Invalid JSON syntax', - }), - isInvalid: true, - }; - } - break; - default: - newUnsavedValue = inputValue; - } + const debouncedUpdateValue = useMemo(() => { + // Trigger update 1000 ms after the user stopped typing to reduce validation requests to the server + return debounce(updateValue, 1000); + }, [updateValue]); - onUpdate({ type: field.type, unsavedValue: inputValue, ...errorParams }); + const onChange: CodeEditorProps['onChange'] = async (newValue) => { + // @ts-expect-error + setValue(newValue); + await debouncedUpdateValue(newValue, onUpdate); }; + useEffect(() => { + setValue(inputValue); + }, [inputValue]); + const { id, ariaAttributes } = field; const { ariaLabel, ariaDescribedBy } = ariaAttributes; - // @ts-expect-error - const [value] = getFieldInputValue(field, unsavedChange); return (
diff --git a/packages/kbn-management/settings/components/field_input/input/json_editor_input.test.tsx b/packages/kbn-management/settings/components/field_input/input/json_editor_input.test.tsx index 800a807f8103a..ecc132dad8c89 100644 --- a/packages/kbn-management/settings/components/field_input/input/json_editor_input.test.tsx +++ b/packages/kbn-management/settings/components/field_input/input/json_editor_input.test.tsx @@ -16,6 +16,7 @@ import { CodeEditorProps } from '../code_editor'; const name = 'Some json field'; const id = 'some:json:field'; const initialValue = '{"foo":"bar"}'; +import { wrap } from '../mocks'; jest.mock('../code_editor', () => ({ CodeEditor: ({ value, onChange }: CodeEditorProps) => ( @@ -55,51 +56,46 @@ describe('JsonEditorInput', () => { }); it('renders without errors', () => { - const { container } = render(); + const { container } = render(wrap()); expect(container).toBeInTheDocument(); }); it('renders the value prop', () => { - const { getByTestId } = render(); + const { getByTestId } = render(wrap()); const input = getByTestId(`${TEST_SUBJ_PREFIX_FIELD}-${id}`); expect(input).toHaveValue(initialValue); }); - it('calls the onInputChange prop when the object value changes', () => { - const { getByTestId } = render(); + it('calls the onInputChange prop when the object value changes', async () => { + const { getByTestId } = render(wrap()); const input = getByTestId(`${TEST_SUBJ_PREFIX_FIELD}-${id}`); fireEvent.change(input, { target: { value: '{"bar":"foo"}' } }); - expect(defaultProps.onInputChange).toHaveBeenCalledWith({ - type: 'json', - unsavedValue: '{"bar":"foo"}', - }); + + await waitFor(() => + expect(defaultProps.onInputChange).toHaveBeenCalledWith({ + type: 'json', + unsavedValue: '{"bar":"foo"}', + }) + ); }); - it('calls the onInputChange prop when the object value changes with no value', () => { - const { getByTestId } = render(); + it('calls the onInputChange prop when the object value changes with no value', async () => { + const { getByTestId } = render(wrap()); const input = getByTestId(`${TEST_SUBJ_PREFIX_FIELD}-${id}`); fireEvent.change(input, { target: { value: '' } }); - expect(defaultProps.onInputChange).toHaveBeenCalledWith({ type: 'json', unsavedValue: '' }); - }); - it('calls the onInputChange prop with an error when the object value changes to invalid JSON', () => { - const { getByTestId } = render(); - const input = getByTestId(`${TEST_SUBJ_PREFIX_FIELD}-${id}`); - fireEvent.change(input, { target: { value: '{"bar" "foo"}' } }); - expect(defaultProps.onInputChange).toHaveBeenCalledWith({ - type: 'json', - unsavedValue: '{"bar" "foo"}', - error: 'Invalid JSON syntax', - isInvalid: true, - }); + await waitFor(() => + expect(defaultProps.onInputChange).toHaveBeenCalledWith({ type: 'json', unsavedValue: '' }) + ); }); - it('calls the onInputChange prop when the array value changes', () => { + it('calls the onInputChange prop when the array value changes', async () => { const props = { ...defaultProps, defaultValue: '["bar", "foo"]', value: undefined }; - const { getByTestId } = render(); + const { getByTestId } = render(wrap()); const input = getByTestId(`${TEST_SUBJ_PREFIX_FIELD}-${id}`); fireEvent.change(input, { target: { value: '["foo", "bar", "baz"]' } }); - waitFor(() => + + await waitFor(() => expect(defaultProps.onInputChange).toHaveBeenCalledWith({ type: 'json', unsavedValue: '["foo", "bar", "baz"]', @@ -107,28 +103,18 @@ describe('JsonEditorInput', () => { ); }); - it('calls the onInputChange prop when the array value changes with no value', () => { + it('calls the onInputChange prop when the array value changes with no value', async () => { const props = { ...defaultProps, defaultValue: '["bar", "foo"]', value: '["bar", "foo"]', }; - const { getByTestId } = render(); + const { getByTestId } = render(wrap()); const input = getByTestId(`${TEST_SUBJ_PREFIX_FIELD}-${id}`); fireEvent.change(input, { target: { value: '' } }); - expect(defaultProps.onInputChange).toHaveBeenCalledWith({ type: 'json', unsavedValue: '' }); - }); - it('calls the onInputChange prop with an array when the array value changes to invalid JSON', () => { - const props = { ...defaultProps, defaultValue: '["bar", "foo"]', value: undefined }; - const { getByTestId } = render(); - const input = getByTestId(`${TEST_SUBJ_PREFIX_FIELD}-${id}`); - fireEvent.change(input, { target: { value: '["bar", "foo" | "baz"]' } }); - expect(defaultProps.onInputChange).toHaveBeenCalledWith({ - type: 'json', - unsavedValue: '["bar", "foo" | "baz"]', - error: 'Invalid JSON syntax', - isInvalid: true, - }); + await waitFor(() => + expect(defaultProps.onInputChange).toHaveBeenCalledWith({ type: 'json', unsavedValue: '' }) + ); }); }); diff --git a/packages/kbn-management/settings/components/field_input/input/markdown_editor_input.test.tsx b/packages/kbn-management/settings/components/field_input/input/markdown_editor_input.test.tsx index 291585e5f149a..f26e59e43efbd 100644 --- a/packages/kbn-management/settings/components/field_input/input/markdown_editor_input.test.tsx +++ b/packages/kbn-management/settings/components/field_input/input/markdown_editor_input.test.tsx @@ -7,11 +7,12 @@ */ import React from 'react'; -import { render, fireEvent } from '@testing-library/react'; +import { render, fireEvent, waitFor } from '@testing-library/react'; import { CodeEditorInput, CodeEditorInputProps } from './code_editor_input'; import { TEST_SUBJ_PREFIX_FIELD } from '.'; import { CodeEditorProps } from '../code_editor'; +import { wrap } from '../mocks'; const name = 'Some markdown field'; const id = 'some:markdown:field'; @@ -55,23 +56,26 @@ describe('MarkdownEditorInput', () => { }); it('renders without errors', () => { - const { container } = render(); + const { container } = render(wrap()); expect(container).toBeInTheDocument(); }); it('renders the value prop', () => { - const { getByTestId } = render(); + const { getByTestId } = render(wrap()); const input = getByTestId(`${TEST_SUBJ_PREFIX_FIELD}-${id}`); expect(input).toHaveValue(initialValue); }); - it('calls the onInputChange prop when the value changes', () => { - const { getByTestId } = render(); + it('calls the onInputChange prop when the value changes', async () => { + const { getByTestId } = render(wrap()); const input = getByTestId(`${TEST_SUBJ_PREFIX_FIELD}-${id}`); fireEvent.change(input, { target: { value: '# New Markdown Title' } }); - expect(defaultProps.onInputChange).toHaveBeenCalledWith({ - type: 'markdown', - unsavedValue: '# New Markdown Title', - }); + + await waitFor(() => + expect(defaultProps.onInputChange).toHaveBeenCalledWith({ + type: 'markdown', + unsavedValue: '# New Markdown Title', + }) + ); }); }); diff --git a/packages/kbn-management/settings/components/field_input/input/number_input.test.tsx b/packages/kbn-management/settings/components/field_input/input/number_input.test.tsx index fa228a48b721e..968982759a1dc 100644 --- a/packages/kbn-management/settings/components/field_input/input/number_input.test.tsx +++ b/packages/kbn-management/settings/components/field_input/input/number_input.test.tsx @@ -65,14 +65,17 @@ describe('NumberInput', () => { expect(input).toHaveValue(4321); }); - it('calls the onInputChange prop when the value changes', () => { + it('calls the onInputChange prop when the value changes', async () => { const { getByTestId } = render(wrap()); const input = getByTestId(`${TEST_SUBJ_PREFIX_FIELD}-${id}`); fireEvent.change(input, { target: { value: '54321' } }); - expect(defaultProps.onInputChange).toHaveBeenCalledWith({ - type: 'number', - unsavedValue: 54321, - }); + + await waitFor(() => + expect(defaultProps.onInputChange).toHaveBeenCalledWith({ + type: 'number', + unsavedValue: 54321, + }) + ); }); it('disables the input when isDisabled prop is true', () => { diff --git a/packages/kbn-management/settings/components/field_input/input/number_input.tsx b/packages/kbn-management/settings/components/field_input/input/number_input.tsx index a1929593e3cb5..8a29429eff59f 100644 --- a/packages/kbn-management/settings/components/field_input/input/number_input.tsx +++ b/packages/kbn-management/settings/components/field_input/input/number_input.tsx @@ -6,13 +6,15 @@ * Side Public License, v 1. */ -import React from 'react'; +import React, { useCallback, useEffect, useMemo, useState } from 'react'; import { EuiFieldNumber, EuiFieldNumberProps } from '@elastic/eui'; import { getFieldInputValue, useUpdate } from '@kbn/management-settings-utilities'; +import { debounce } from 'lodash'; import { InputProps } from '../types'; import { TEST_SUBJ_PREFIX_FIELD } from '.'; +import { useServices } from '../services'; /** * Props for a {@link NumberInput} component. @@ -28,18 +30,45 @@ export const NumberInput = ({ isSavingEnabled, onInputChange, }: NumberInputProps) => { - const onChange: EuiFieldNumberProps['onChange'] = (event) => { - const inputValue = Number(event.target.value); - onUpdate({ type: field.type, unsavedValue: inputValue }); + const [inputValue] = getFieldInputValue(field, unsavedChange) || undefined; + const [value, setValue] = useState(inputValue); + const { validateChange } = useServices(); + const onUpdate = useUpdate({ onInputChange, field }); + + const updateValue = useCallback( + async (newValue: number, onUpdateFn) => { + const validationResponse = await validateChange(field.id, newValue); + if (validationResponse.successfulValidation && !validationResponse.valid) { + onUpdateFn({ + type: field.type, + unsavedValue: newValue, + isInvalid: !validationResponse.valid, + error: validationResponse.errorMessage, + }); + } else { + onUpdateFn({ type: field.type, unsavedValue: newValue }); + } + }, + [validateChange, field.id, field.type] + ); + + const debouncedUpdateValue = useMemo(() => { + // Trigger update 500 ms after the user stopped typing to reduce validation requests to the server + return debounce(updateValue, 500); + }, [updateValue]); + + const onChange: EuiFieldNumberProps['onChange'] = async (event) => { + const newValue = Number(event.target.value); + setValue(newValue); + await debouncedUpdateValue(newValue, onUpdate); }; - const onUpdate = useUpdate({ onInputChange, field }); + useEffect(() => { + setValue(inputValue); + }, [inputValue]); const { id, name, ariaAttributes } = field; const { ariaLabel, ariaDescribedBy } = ariaAttributes; - const [rawValue] = getFieldInputValue(field, unsavedChange); - - const value = rawValue === null ? undefined : rawValue; return ( { export const createFieldInputServicesMock = (): FieldInputServices => ({ showDanger: jest.fn(), + validateChange: async () => { + return { successfulValidation: true, valid: true }; + }, }); export const TestWrapper = ({ diff --git a/packages/kbn-management/settings/components/field_input/services.tsx b/packages/kbn-management/settings/components/field_input/services.tsx index 95a6474f89b58..d19278268b2a6 100644 --- a/packages/kbn-management/settings/components/field_input/services.tsx +++ b/packages/kbn-management/settings/components/field_input/services.tsx @@ -17,9 +17,13 @@ const FieldInputContext = React.createContext(null); export const FieldInputProvider: FC = ({ children, ...services }) => { // Typescript types are widened to accept more than what is needed. Take only what is necessary // so the context remains clean. - const { showDanger } = services; + const { showDanger, validateChange } = services; - return {children}; + return ( + + {children} + + ); }; /** @@ -28,11 +32,15 @@ export const FieldInputProvider: FC = ({ children, ...servic export const FieldInputKibanaProvider: FC = ({ children, notifications: { toasts }, + settings: { client }, }) => { return ( toasts.addDanger(message), + validateChange: async (key, value) => { + return await client.validateValue(key, value); + }, }} > {children} diff --git a/packages/kbn-management/settings/components/field_input/tsconfig.json b/packages/kbn-management/settings/components/field_input/tsconfig.json index bc47a21a3d752..bb4c6b4aa57d0 100644 --- a/packages/kbn-management/settings/components/field_input/tsconfig.json +++ b/packages/kbn-management/settings/components/field_input/tsconfig.json @@ -29,5 +29,6 @@ "@kbn/core-theme-browser-mocks", "@kbn/core-i18n-browser", "@kbn/core-analytics-browser-mocks", + "@kbn/core-ui-settings-browser", ] } diff --git a/packages/kbn-management/settings/components/field_input/types.ts b/packages/kbn-management/settings/components/field_input/types.ts index e1c2ce1a70dfb..f6eed155a1891 100644 --- a/packages/kbn-management/settings/components/field_input/types.ts +++ b/packages/kbn-management/settings/components/field_input/types.ts @@ -13,6 +13,8 @@ import { UnsavedFieldChange, } from '@kbn/management-settings-types'; import { ToastsStart } from '@kbn/core-notifications-browser'; +import { IUiSettingsClient } from '@kbn/core-ui-settings-browser'; +import { ValueValidation } from '@kbn/core-ui-settings-browser/src/types'; /** * Contextual services used by a {@link FieldInput} component. @@ -23,6 +25,7 @@ export interface FieldInputServices { * @param value The message to display. */ showDanger: (value: string) => void; + validateChange: (key: string, value: any) => Promise; } /** @@ -34,6 +37,9 @@ export interface FieldInputKibanaDependencies { notifications: { toasts: Pick; }; + settings: { + client: IUiSettingsClient; + }; } /** diff --git a/packages/kbn-management/settings/components/field_row/__stories__/common.tsx b/packages/kbn-management/settings/components/field_row/__stories__/common.tsx index e8c51d075c21d..5b20b5fcf24ba 100644 --- a/packages/kbn-management/settings/components/field_row/__stories__/common.tsx +++ b/packages/kbn-management/settings/components/field_row/__stories__/common.tsx @@ -78,6 +78,13 @@ export const getStory = ( { + action(`validateChange`)({ + key, + value, + }); + return { successfulValidation: true, valid: true }; + }} > diff --git a/packages/kbn-management/settings/components/field_row/services.tsx b/packages/kbn-management/settings/components/field_row/services.tsx index 10963041837e6..6350b7f7cd103 100644 --- a/packages/kbn-management/settings/components/field_row/services.tsx +++ b/packages/kbn-management/settings/components/field_row/services.tsx @@ -29,11 +29,11 @@ export interface FieldRowProviderProps extends FieldRowServices { export const FieldRowProvider = ({ children, ...services }: FieldRowProviderProps) => { // Typescript types are widened to accept more than what is needed. Take only what is necessary // so the context remains clean. - const { links, showDanger } = services; + const { links, showDanger, validateChange } = services; return ( - {children} + {children} ); }; @@ -45,6 +45,7 @@ export const FieldRowKibanaProvider: FC = ({ children, docLinks, notifications, + settings, }) => { return ( = ({ links: docLinks.links.management, }} > - {children} + + {children} + ); }; diff --git a/packages/kbn-management/settings/components/form/services.tsx b/packages/kbn-management/settings/components/form/services.tsx index e0a48807b351f..39aac8b4ecb01 100644 --- a/packages/kbn-management/settings/components/form/services.tsx +++ b/packages/kbn-management/settings/components/form/services.tsx @@ -56,7 +56,7 @@ export const FormKibanaProvider: FC = ({ children, ...de return ( - + {children} diff --git a/packages/kbn-management/settings/components/form/storybook/form.stories.tsx b/packages/kbn-management/settings/components/form/storybook/form.stories.tsx index dce99b908d650..235ca90f9bef1 100644 --- a/packages/kbn-management/settings/components/form/storybook/form.stories.tsx +++ b/packages/kbn-management/settings/components/form/storybook/form.stories.tsx @@ -37,6 +37,13 @@ export default { saveChanges={action('saveChanges')} showError={action('showError')} showReloadPagePrompt={action('showReloadPagePrompt')} + validateChange={async (key, value) => { + action(`validateChange`)({ + key, + value, + }); + return { successfulValidation: true, valid: true }; + }} > diff --git a/packages/kbn-osquery-io-ts-types/src/live_query/index.ts b/packages/kbn-osquery-io-ts-types/src/live_query/index.ts index 378bb446cafab..6fc9af23a6a72 100644 --- a/packages/kbn-osquery-io-ts-types/src/live_query/index.ts +++ b/packages/kbn-osquery-io-ts-types/src/live_query/index.ts @@ -7,6 +7,7 @@ */ import * as t from 'io-ts'; +import { inRangeRt } from '@kbn/io-ts-utils'; export const id = t.string; export type Id = t.TypeOf; @@ -49,6 +50,11 @@ export type Interval = t.TypeOf; export const intervalOrUndefined = t.union([interval, t.undefined]); export type IntervalOrUndefined = t.TypeOf; +export const timeout = inRangeRt(60, 60 * 15); +export type Timeout = t.TypeOf; +export const timeoutOrUndefined = t.union([timeout, t.undefined]); +export type TimeoutOrUndefined = t.TypeOf; + export const snapshot = t.boolean; export type Snapshot = t.TypeOf; export const snapshotOrUndefined = t.union([snapshot, t.undefined]); diff --git a/packages/kbn-osquery-io-ts-types/tsconfig.json b/packages/kbn-osquery-io-ts-types/tsconfig.json index b72f7b0a15c5c..780216a67a247 100644 --- a/packages/kbn-osquery-io-ts-types/tsconfig.json +++ b/packages/kbn-osquery-io-ts-types/tsconfig.json @@ -12,5 +12,8 @@ ], "exclude": [ "target/**/*", + ], + "kbn_references": [ + "@kbn/io-ts-utils", ] } diff --git a/packages/kbn-plugin-generator/template/server/index.ts.ejs b/packages/kbn-plugin-generator/template/server/index.ts.ejs index 5e0510b7ecb86..68cce4a2157c9 100644 --- a/packages/kbn-plugin-generator/template/server/index.ts.ejs +++ b/packages/kbn-plugin-generator/template/server/index.ts.ejs @@ -1,11 +1,10 @@ import { PluginInitializerContext } from '<%= importFromRoot('src/core/server') %>'; -import { <%= upperCamelCase(name) %>Plugin } from './plugin'; - // This exports static code and TypeScript types, // as well as, Kibana Platform `plugin()` initializer. - export function plugin(initializerContext: PluginInitializerContext) { +export async function plugin(initializerContext: PluginInitializerContext) { + const { <%= upperCamelCase(name) %>Plugin } = await import('./plugin'); return new <%= upperCamelCase(name) %>Plugin(initializerContext); } diff --git a/packages/kbn-reporting/common/README.md b/packages/kbn-reporting/common/README.md index 3b40bc8ff8b93..1b53a6ea0de61 100644 --- a/packages/kbn-reporting/common/README.md +++ b/packages/kbn-reporting/common/README.md @@ -2,4 +2,4 @@ Removes any circular dependency from the reporting plugin and the @kbn/generate-csv package. -This package includes the `CancellationToken` class, schema utils, constants, errors that extend `ReportingError`, and metrics such as `TaskRunResult`. p \ No newline at end of file +This package includes the `CancellationToken` class, schema utils, constants, errors that extend `ReportingError`, and metrics such as `TaskRunResult`. This package is shared-common vs specifically server or browser. The `@kbn/reporting-server` package has the server side helpers. \ No newline at end of file diff --git a/x-pack/plugins/reporting/common/build_kibana_path.ts b/packages/kbn-reporting/common/build_kibana_path.ts similarity index 71% rename from x-pack/plugins/reporting/common/build_kibana_path.ts rename to packages/kbn-reporting/common/build_kibana_path.ts index 2cb37013300ca..b719d6a68f23a 100644 --- a/x-pack/plugins/reporting/common/build_kibana_path.ts +++ b/packages/kbn-reporting/common/build_kibana_path.ts @@ -1,8 +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. + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. */ interface Args { diff --git a/packages/kbn-reporting/common/constants.ts b/packages/kbn-reporting/common/constants.ts index f2bf7e7e99a80..02926a53a14eb 100644 --- a/packages/kbn-reporting/common/constants.ts +++ b/packages/kbn-reporting/common/constants.ts @@ -5,7 +5,74 @@ * in compliance with, at your election, the Elastic License 2.0 or the Server * Side Public License, v 1. */ + +export const PLUGIN_ID = 'reporting'; + +export const ALLOWED_JOB_CONTENT_TYPES = [ + 'application/json', + 'application/pdf', + 'text/csv', + 'image/png', + 'text/plain', +]; + +// APM +export const REPORTING_TRANSACTION_TYPE = PLUGIN_ID; + +export const REPORTING_REDIRECT_LOCATOR_STORE_KEY = '__REPORTING_REDIRECT_LOCATOR_STORE_KEY__'; + export const UI_SETTINGS_SEARCH_INCLUDE_FROZEN = 'search:includeFrozen'; export const UI_SETTINGS_CUSTOM_PDF_LOGO = 'xpackReporting:customPdfLogo'; export const UI_SETTINGS_DATEFORMAT_TZ = 'dateFormat:tz'; -export const CSV_REPORTING_ACTION = 'downloadCsvReport'; + +// Licenses +export const LICENSE_TYPE_TRIAL = 'trial' as const; +export const LICENSE_TYPE_BASIC = 'basic' as const; +export const LICENSE_TYPE_CLOUD_STANDARD = 'standard' as const; +export const LICENSE_TYPE_GOLD = 'gold' as const; +export const LICENSE_TYPE_PLATINUM = 'platinum' as const; +export const LICENSE_TYPE_ENTERPRISE = 'enterprise' as const; + +export const REPORTING_SYSTEM_INDEX = '.reporting'; + +export const JOB_COMPLETION_NOTIFICATIONS_SESSION_KEY = + 'xpack.reporting.jobCompletionNotifications'; + +/** + * A way to get the client side route for the reporting redirect app. + * + * TODO: Add a job ID and a locator to use so that we can redirect without expecting state to + * be injected to the page + */ +export const getRedirectAppPath = () => { + return '/app/reportingRedirect'; +}; + +export const ILM_POLICY_NAME = 'kibana-reporting'; + +// Usage counter types +export const API_USAGE_COUNTER_TYPE = 'reportingApi'; +export const API_USAGE_ERROR_TYPE = 'reportingApiError'; + +// Management UI route +export const REPORTING_MANAGEMENT_HOME = '/app/management/insightsAndAlerting/reporting'; + +/* + * JobStatus: + * - Begins as 'pending' + * - Changes to 'processing` when the job is claimed + * - Then 'completed' | 'failed' when execution is done + * If the job needs a retry, it reverts back to 'pending'. + */ +export enum JOB_STATUS { + PENDING = 'pending', + PROCESSING = 'processing', + COMPLETED = 'completed', + FAILED = 'failed', + WARNINGS = 'completed_with_warnings', +} + +// Job params require a `version` field as of 7.15.0. For older jobs set with +// automation that have no version value in the job params, we assume the +// intended version is 7.14.0 +export const UNVERSIONED_VERSION = '7.14.0'; diff --git a/packages/kbn-reporting/common/index.ts b/packages/kbn-reporting/common/index.ts index 8b1636c1fbc22..b299ae3a6eff3 100644 --- a/packages/kbn-reporting/common/index.ts +++ b/packages/kbn-reporting/common/index.ts @@ -6,8 +6,9 @@ * Side Public License, v 1. */ -export { CancellationToken } from './cancellation_token'; -export type { TaskRunMetrics, CsvMetrics, TaskRunResult } from './metrics'; -export * from './errors'; export * from './constants'; +export * from './errors'; export * from './schema_utils'; + +export { CancellationToken } from './cancellation_token'; +export { buildKibanaPath } from './build_kibana_path'; diff --git a/packages/kbn-reporting/common/kibana.jsonc b/packages/kbn-reporting/common/kibana.jsonc index 1a6681268635e..9b03854836915 100644 --- a/packages/kbn-reporting/common/kibana.jsonc +++ b/packages/kbn-reporting/common/kibana.jsonc @@ -1,5 +1,5 @@ { "type": "shared-common", "id": "@kbn/reporting-common", - "owner": "@elastic/appex-sharedux" + "owner": "@elastic/appex-sharedux", } diff --git a/packages/kbn-reporting/common/metrics.ts b/packages/kbn-reporting/common/metrics.ts deleted file mode 100644 index a1ac55ddf6360..0000000000000 --- a/packages/kbn-reporting/common/metrics.ts +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may 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 { PdfScreenshotResult, PngScreenshotResult } from '@kbn/screenshotting-plugin/server'; - -export type PngMetrics = PngScreenshotResult['metrics']; - -export type PdfMetrics = PdfScreenshotResult['metrics']; - -export interface CsvMetrics { - rows: number; -} - -export interface TaskRunMetrics { - csv?: CsvMetrics; - png?: PngMetrics; - pdf?: PdfMetrics; -} - -export interface TaskRunResult { - content_type: string | null; - csv_contains_formulas?: boolean; - max_size_reached?: boolean; - warnings?: string[]; - metrics?: TaskRunMetrics; - /** - * When running a report task we may finish with warnings that were triggered - * by an error. We can pass the error code via the task run result to the - * task runner so that it can be recorded for telemetry. - * - * Alternatively, this field can be populated in the event that the task does - * not complete in the task runner's error handler. - */ - error_code?: string; -} diff --git a/packages/kbn-reporting/common/tsconfig.json b/packages/kbn-reporting/common/tsconfig.json index 9a68b802c21f4..80ed6308f02ff 100644 --- a/packages/kbn-reporting/common/tsconfig.json +++ b/packages/kbn-reporting/common/tsconfig.json @@ -5,7 +5,6 @@ "types": [ "jest", "node", - "react" ] }, "include": [ @@ -16,8 +15,9 @@ "target/**/*" ], "kbn_references": [ - "@kbn/i18n", - "@kbn/screenshotting-plugin", "@kbn/config-schema", + "@kbn/utility-types", + "@kbn/screenshotting-plugin", + "@kbn/i18n", ] } diff --git a/x-pack/plugins/reporting/common/types/index.ts b/packages/kbn-reporting/common/types.ts similarity index 56% rename from x-pack/plugins/reporting/common/types/index.ts rename to packages/kbn-reporting/common/types.ts index 48968e17a1cb9..a208bd24226f1 100644 --- a/x-pack/plugins/reporting/common/types/index.ts +++ b/packages/kbn-reporting/common/types.ts @@ -1,37 +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. + * 2.0 and the Server Side Public License, v 1; you may 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 { TaskRunMetrics, TaskRunResult } from '@kbn/reporting-common'; -import type { PdfScreenshotResult, PngScreenshotResult } from '@kbn/screenshotting-plugin/server'; -import type { BaseParams, BaseParamsV2, BasePayload, BasePayloadV2, JobId } from './base'; - -export type { - JobParamsCsvFromSavedObject, - TaskPayloadCsvFromSavedObject, -} from './export_types/csv_v2'; -export type { JobParamsPNGDeprecated } from './export_types/png'; -export type { JobParamsPNGV2 } from './export_types/png_v2'; -export type { JobAppParamsPDF, JobParamsPDFDeprecated } from './export_types/printable_pdf'; -export type { JobAppParamsPDFV2, JobParamsPDFV2 } from './export_types/printable_pdf_v2'; -export type { - DownloadReportFn, - IlmPolicyMigrationStatus, - IlmPolicyStatusResponse, - LocatorParams, - ManagementLinkFn, - UrlOrUrlLocatorTuple, -} from './url'; -export type { JobId, BaseParams, BaseParamsV2, BasePayload, BasePayloadV2 }; +import type { + LayoutParams, + PerformanceMetrics as ScreenshotMetrics, +} from '@kbn/screenshotting-plugin/common'; +import { JOB_STATUS } from './constants'; +import type { LocatorParams } from './url'; -export interface ReportDocumentHead { - _id: string; - _index: string; - _seq_no: number; - _primary_term: number; +export * from './url'; + +export interface CsvMetrics { + rows: number; +} + +export interface TaskRunMetrics { + csv?: CsvMetrics; + png?: ScreenshotMetrics; + pdf?: ScreenshotMetrics & { pages?: number }; +} + +export interface TaskRunResult { + content_type: string | null; + csv_contains_formulas?: boolean; + max_size_reached?: boolean; + warnings?: string[]; + metrics?: TaskRunMetrics; + /** + * When running a report task we may finish with warnings that were triggered + * by an error. We can pass the error code via the task run result to the + * task runner so that it can be recorded for telemetry. + * + * Alternatively, this field can be populated in the event that the task does + * not complete in the task runner's error handler. + */ + error_code?: string; } export interface ReportOutput extends TaskRunResult { @@ -39,9 +47,66 @@ export interface ReportOutput extends TaskRunResult { size: number; } -export type PngMetrics = PngScreenshotResult['metrics']; +/** + * @deprecated + */ +export interface BaseParams { + layout?: LayoutParams; + objectType: string; + title: string; + browserTimezone: string; // to format dates in the user's time zone + version: string; // to handle any state migrations +} + +/** + * Report job parameters that an application must return from its + * getSharingData function. + */ +export type BaseParamsV2 = BaseParams & { + locatorParams: LocatorParams[]; +}; + +/** + * @deprecated + */ +export interface BasePayload extends BaseParams { + headers: string; + spaceId?: string; + isDeprecated?: boolean; +} -export type PdfMetrics = PdfScreenshotResult['metrics']; +export type JobId = string; + +/** + * Report job parameters, after they are processed in the request handler. + */ +export interface BasePayloadV2 extends BaseParamsV2 { + headers: string; + spaceId?: string; + isDeprecated?: boolean; +} + +export interface ReportingServerInfo { + basePath: string; + protocol: string; + hostname: string; + port: number; + name: string; + uuid: string; +} + +export type IlmPolicyMigrationStatus = 'policy-not-found' | 'indices-not-managed-by-policy' | 'ok'; + +export interface IlmPolicyStatusResponse { + status: IlmPolicyMigrationStatus; +} + +export interface ReportDocumentHead { + _id: string; + _index: string; + _seq_no: number; + _primary_term: number; +} export interface ReportFields { queue_time_ms?: number[]; // runtime field: started_at - created_at @@ -65,7 +130,7 @@ export interface ReportSource { migration_version: string; // for reminding the user to update their POST URL attempts: number; // initially populated as 0 created_at: string; // timestamp in UTC - status: JobStatus; + status: JOB_STATUS; /* * `output` is only populated if the report job is completed or failed. @@ -93,20 +158,6 @@ export interface ReportDocument extends ReportDocumentHead { _source: ReportSource; } -/* - * JobStatus: - * - Begins as 'pending' - * - Changes to 'processing` when the job is claimed - * - Then 'completed' | 'failed' when execution is done - * If the job needs a retry, it reverts back to 'pending'. - */ -export type JobStatus = - | 'completed' // Report was successful - | 'completed_with_warnings' // The download available for troubleshooting - it **should** show a meaningful error - | 'pending' // Report job is waiting to be claimed - | 'processing' // Report job has been claimed and is executing - | 'failed'; // Report was not successful, and all retries are done. Nothing to download. - /* * Info API response: to avoid unnecessary large payloads on a network, the * report query results do not include `payload.headers` or `output.content`, @@ -132,19 +183,3 @@ export interface LicenseCheckResults { showLinks: boolean; message: string; } - -/* Notifier Toasts */ -export interface JobSummary { - id: JobId; - status: JobStatus; - jobtype: ReportSource['jobtype']; - title: ReportSource['payload']['title']; - errorCode?: ReportOutput['error_code']; - maxSizeReached: TaskRunResult['max_size_reached']; - csvContainsFormulas: TaskRunResult['csv_contains_formulas']; -} - -export interface JobSummarySet { - completed: JobSummary[]; - failed: JobSummary[]; -} diff --git a/x-pack/plugins/reporting/common/types/url.ts b/packages/kbn-reporting/common/url.ts similarity index 81% rename from x-pack/plugins/reporting/common/types/url.ts rename to packages/kbn-reporting/common/url.ts index 2445e210b89b7..14772b3a612aa 100644 --- a/x-pack/plugins/reporting/common/types/url.ts +++ b/packages/kbn-reporting/common/url.ts @@ -1,12 +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. + * 2.0 and the Server Side Public License, v 1; you may 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 { SerializableRecord } from '@kbn/utility-types'; -import type { JobId } from './base'; +import type { JobId } from './types'; type DownloadLink = string; export type DownloadReportFn = (jobId: JobId) => DownloadLink; diff --git a/packages/kbn-reporting/export_types/csv/README.md b/packages/kbn-reporting/export_types/csv/README.md new file mode 100644 index 0000000000000..633acff099614 --- /dev/null +++ b/packages/kbn-reporting/export_types/csv/README.md @@ -0,0 +1,4 @@ +@kbn/reporting-export-types-csv + +This package originally was part of the reporting plugin. It is now extracted into its own package that includes the csv export classes that are then used in the reporting plugin. + diff --git a/x-pack/plugins/reporting/server/export_types/csv_searchsource/csv_searchsource.test.ts b/packages/kbn-reporting/export_types/csv/csv_searchsource.test.ts similarity index 78% rename from x-pack/plugins/reporting/server/export_types/csv_searchsource/csv_searchsource.test.ts rename to packages/kbn-reporting/export_types/csv/csv_searchsource.test.ts index 6596fc41d66d8..f48c25695405e 100644 --- a/x-pack/plugins/reporting/server/export_types/csv_searchsource/csv_searchsource.test.ts +++ b/packages/kbn-reporting/export_types/csv/csv_searchsource.test.ts @@ -1,8 +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. + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. */ jest.mock('@kbn/generate-csv', () => ({ @@ -19,23 +20,27 @@ jest.mock('@kbn/generate-csv', () => ({ import nodeCrypto from '@elastic/node-crypto'; import { coreMock, elasticsearchServiceMock, loggingSystemMock } from '@kbn/core/server/mocks'; import { Writable } from 'stream'; -import { ReportingCore } from '../..'; import { CancellationToken } from '@kbn/reporting-common'; -import { createMockConfigSchema, createMockReportingCore } from '../../test_helpers'; -import { CsvSearchSourceExportType } from './csv_searchsource'; import { discoverPluginMock } from '@kbn/discover-plugin/server/mocks'; +import { createFieldFormatsStartMock } from '@kbn/field-formats-plugin/server/mocks'; import { dataPluginMock } from '@kbn/data-plugin/server/mocks'; -import { createMockScreenshottingStart } from '@kbn/screenshotting-plugin/server/mock'; +import { setFieldFormats } from '@kbn/reporting-server'; +import { createMockConfigSchema } from '@kbn/reporting-mocks-server'; + +import { CsvSearchSourceExportType } from '.'; const mockLogger = loggingSystemMock.createLogger(); const encryptionKey = 'tetkey'; const headers = { sid: 'cooltestheaders' }; let encryptedHeaders: string; -let mockReportingCore: ReportingCore; let stream: jest.Mocked; let mockCsvSearchSourceExportType: CsvSearchSourceExportType; beforeAll(async () => { + // use fieldFormats plugin for csv formats + // normally, this is done in the Reporting plugin + setFieldFormats(createFieldFormatsStartMock()); + const crypto = nodeCrypto({ encryptionKey }); encryptedHeaders = await crypto.encrypt(headers); @@ -52,8 +57,6 @@ beforeAll(async () => { const mockCoreStart = coreMock.createStart(); const context = coreMock.createPluginInitializerContext(configType); - mockReportingCore = await createMockReportingCore(configType); - mockCsvSearchSourceExportType = new CsvSearchSourceExportType( mockCoreSetup, configType, @@ -71,8 +74,6 @@ beforeAll(async () => { uiSettings: mockCoreStart.uiSettings, discover: discoverPluginMock.createStartContract(), data: dataPluginMock.createStartContract(), - screenshotting: createMockScreenshottingStart(), - reporting: mockReportingCore.getContract(), }); }); @@ -96,9 +97,9 @@ test('gets the csv content from job parameters', async () => { ); expect(payload).toMatchInlineSnapshot(` - Object { - "content_type": "text/csv", - "size": 123, - } - `); + Object { + "content_type": "text/csv", + "size": 123, + } + `); }); diff --git a/x-pack/plugins/reporting/server/export_types/csv_searchsource/csv_searchsource.ts b/packages/kbn-reporting/export_types/csv/csv_searchsource.ts similarity index 79% rename from x-pack/plugins/reporting/server/export_types/csv_searchsource/csv_searchsource.ts rename to packages/kbn-reporting/export_types/csv/csv_searchsource.ts index 3847c9b45c197..4063495272137 100644 --- a/x-pack/plugins/reporting/server/export_types/csv_searchsource/csv_searchsource.ts +++ b/packages/kbn-reporting/export_types/csv/csv_searchsource.ts @@ -1,33 +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. + * 2.0 and the Server Side Public License, v 1; you may 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 { DataPluginStart } from '@kbn/data-plugin/server/plugin'; -import { DiscoverServerPluginStart } from '@kbn/discover-plugin/server'; -import { CsvGenerator } from '@kbn/generate-csv'; -import { CancellationToken } from '@kbn/reporting-common'; import { Writable } from 'stream'; + +import type { DataPluginStart } from '@kbn/data-plugin/server/plugin'; +import type { DiscoverServerPluginStart } from '@kbn/discover-plugin/server'; +import { CsvGenerator } from '@kbn/generate-csv'; import { - CSV_JOB_TYPE, + CancellationToken, LICENSE_TYPE_BASIC, LICENSE_TYPE_CLOUD_STANDARD, LICENSE_TYPE_ENTERPRISE, LICENSE_TYPE_GOLD, LICENSE_TYPE_PLATINUM, LICENSE_TYPE_TRIAL, -} from '../../../common/constants'; -import { getFieldFormats } from '../../services'; -import { ExportType, BaseExportTypeSetupDeps, BaseExportTypeStartDeps } from '../common'; -import { decryptJobHeaders } from '../common/decrypt_job_headers'; -import { JobParamsCSV, TaskPayloadCSV } from './types'; +} from '@kbn/reporting-common'; +import { + CSV_JOB_TYPE, + CSV_REPORT_TYPE, + JobParamsCSV, + TaskPayloadCSV, +} from '@kbn/reporting-export-types-csv-common'; +import { + BaseExportTypeSetupDeps, + BaseExportTypeStartDeps, + ExportType, + decryptJobHeaders, + getFieldFormats, +} from '@kbn/reporting-server'; type CsvSearchSourceExportTypeSetupDeps = BaseExportTypeSetupDeps; interface CsvSearchSourceExportTypeStartDeps extends BaseExportTypeStartDeps { - discover: DiscoverServerPluginStart; data: DataPluginStart; + discover: DiscoverServerPluginStart; } export class CsvSearchSourceExportType extends ExportType< @@ -36,7 +46,7 @@ export class CsvSearchSourceExportType extends ExportType< CsvSearchSourceExportTypeSetupDeps, CsvSearchSourceExportTypeStartDeps > { - id = 'csv_searchsource'; + id = CSV_REPORT_TYPE; name = CSV_JOB_TYPE; jobType = CSV_JOB_TYPE; jobContentEncoding = 'base64' as const; diff --git a/x-pack/plugins/reporting/server/export_types/csv_searchsource_immediate/csv_searchsource_immediate.ts b/packages/kbn-reporting/export_types/csv/csv_searchsource_immediate.ts similarity index 86% rename from x-pack/plugins/reporting/server/export_types/csv_searchsource_immediate/csv_searchsource_immediate.ts rename to packages/kbn-reporting/export_types/csv/csv_searchsource_immediate.ts index 2a53d138bfd92..ed690935d4582 100644 --- a/x-pack/plugins/reporting/server/export_types/csv_searchsource_immediate/csv_searchsource_immediate.ts +++ b/packages/kbn-reporting/export_types/csv/csv_searchsource_immediate.ts @@ -1,33 +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. + * 2.0 and the Server Side Public License, v 1; you may 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 { Writable } from 'stream'; + import { KibanaRequest } from '@kbn/core-http-server'; import { DataPluginStart } from '@kbn/data-plugin/server/plugin'; import { DiscoverServerPluginStart } from '@kbn/discover-plugin/server'; import { CsvGenerator } from '@kbn/generate-csv'; -import { CancellationToken, TaskRunResult } from '@kbn/reporting-common'; -import { Writable } from 'stream'; import { - ExportType, - BaseExportTypeSetupDeps, - BaseExportTypeStartDeps, -} from '../common/export_type'; -import { - CSV_SEARCHSOURCE_IMMEDIATE_TYPE, + CancellationToken, LICENSE_TYPE_BASIC, LICENSE_TYPE_CLOUD_STANDARD, LICENSE_TYPE_ENTERPRISE, LICENSE_TYPE_GOLD, LICENSE_TYPE_PLATINUM, LICENSE_TYPE_TRIAL, -} from '../../../common/constants'; -import { getFieldFormats } from '../../services'; -import { ReportingRequestHandlerContext } from '../../types'; -import { JobParamsDownloadCSV } from './types'; +} from '@kbn/reporting-common'; +import type { TaskRunResult } from '@kbn/reporting-common/types'; +import { + CSV_SEARCHSOURCE_IMMEDIATE_TYPE, + JobParamsDownloadCSV, +} from '@kbn/reporting-export-types-csv-common'; +import type { BaseExportTypeSetupDeps, BaseExportTypeStartDeps } from '@kbn/reporting-server'; +import { ExportType, getFieldFormats } from '@kbn/reporting-server'; + +import { ReportingRequestHandlerContext } from './types'; type CsvSearchSourceImmediateExportTypeSetupDeps = BaseExportTypeSetupDeps; interface CsvSearchSourceImmediateExportTypeStartDeps extends BaseExportTypeStartDeps { diff --git a/x-pack/plugins/reporting/server/export_types/csv_v2/csv_v2.ts b/packages/kbn-reporting/export_types/csv/csv_v2.ts similarity index 83% rename from x-pack/plugins/reporting/server/export_types/csv_v2/csv_v2.ts rename to packages/kbn-reporting/export_types/csv/csv_v2.ts index 921c0724d8439..9ef87011ba6dc 100644 --- a/x-pack/plugins/reporting/server/export_types/csv_v2/csv_v2.ts +++ b/packages/kbn-reporting/export_types/csv/csv_v2.ts @@ -1,33 +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. + * 2.0 and the Server Side Public License, v 1; you may 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 Boom from '@hapi/boom'; -import { KibanaRequest } from '@kbn/core/server'; -import { DiscoverServerPluginStart } from '@kbn/discover-plugin/server'; -import { DataPluginStart } from '@kbn/data-plugin/server/plugin'; -import { CsvGenerator } from '@kbn/generate-csv'; import { Writable } from 'stream'; -import { CancellationToken } from '@kbn/reporting-common'; -import { JobParamsCsvFromSavedObject, TaskPayloadCsvFromSavedObject } from '../../../common/types'; + +import type { KibanaRequest } from '@kbn/core/server'; +import type { DataPluginStart } from '@kbn/data-plugin/server/plugin'; +import type { DiscoverServerPluginStart } from '@kbn/discover-plugin/server'; +import { CsvGenerator } from '@kbn/generate-csv'; import { - CSV_REPORT_TYPE_V2, + CancellationToken, LICENSE_TYPE_BASIC, LICENSE_TYPE_CLOUD_STANDARD, LICENSE_TYPE_ENTERPRISE, LICENSE_TYPE_GOLD, LICENSE_TYPE_PLATINUM, LICENSE_TYPE_TRIAL, -} from '../../../common/constants'; -import { ExportType, BaseExportTypeSetupDeps, BaseExportTypeStartDeps } from '../common'; -import { ReportingRequestHandlerContext } from '../../types'; -import { getFieldFormats } from '../../services'; -import { decryptJobHeaders } from '../common/decrypt_job_headers'; +} from '@kbn/reporting-common'; +import { + CSV_REPORT_TYPE_V2, + JobParamsCsvFromSavedObject, + TaskPayloadCsvFromSavedObject, +} from '@kbn/reporting-export-types-csv-common'; +import { + ExportType, + decryptJobHeaders, + getFieldFormats, + type BaseExportTypeSetupDeps, + type BaseExportTypeStartDeps, +} from '@kbn/reporting-server'; + +import { ReportingRequestHandlerContext } from './types'; type CsvV2ExportTypeSetupDeps = BaseExportTypeSetupDeps; + export interface CsvV2ExportTypeStartDeps extends BaseExportTypeStartDeps { discover: DiscoverServerPluginStart; data: DataPluginStart; @@ -55,8 +66,7 @@ export class CsvV2ExportType extends ExportType< constructor(...args: ConstructorParameters) { super(...args); - const logger = args[2]; - this.logger = logger.get('csv-export-v2'); + this.logger = this.logger.get('csv-export-v2'); } public createJob = async ( diff --git a/packages/kbn-reporting/export_types/csv/index.ts b/packages/kbn-reporting/export_types/csv/index.ts new file mode 100644 index 0000000000000..a5cddaebe4821 --- /dev/null +++ b/packages/kbn-reporting/export_types/csv/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 { CsvSearchSourceExportType } from './csv_searchsource'; +export { CsvV2ExportType } from './csv_v2'; +export { CsvSearchSourceImmediateExportType } from './csv_searchsource_immediate'; diff --git a/packages/kbn-reporting/export_types/csv/jest.config.js b/packages/kbn-reporting/export_types/csv/jest.config.js new file mode 100644 index 0000000000000..3f14bdeaba318 --- /dev/null +++ b/packages/kbn-reporting/export_types/csv/jest.config.js @@ -0,0 +1,13 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +module.exports = { + preset: '@kbn/test/jest_node', + rootDir: '../../../..', + roots: ['/packages/kbn-reporting/export_types/csv'], +}; diff --git a/packages/kbn-reporting/export_types/csv/kibana.jsonc b/packages/kbn-reporting/export_types/csv/kibana.jsonc new file mode 100644 index 0000000000000..e638d40ede567 --- /dev/null +++ b/packages/kbn-reporting/export_types/csv/kibana.jsonc @@ -0,0 +1,5 @@ +{ + "type": "shared-server", + "id": "@kbn/reporting-export-types-csv", + "owner": "@elastic/appex-sharedux" + } \ No newline at end of file diff --git a/packages/kbn-reporting/export_types/csv/package.json b/packages/kbn-reporting/export_types/csv/package.json new file mode 100644 index 0000000000000..81e9a4d1c4172 --- /dev/null +++ b/packages/kbn-reporting/export_types/csv/package.json @@ -0,0 +1,6 @@ +{ + "name": "@kbn/reporting-export-types-csv", + "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/kbn-reporting/export_types/csv/tsconfig.json b/packages/kbn-reporting/export_types/csv/tsconfig.json new file mode 100644 index 0000000000000..ba5f294cfa935 --- /dev/null +++ b/packages/kbn-reporting/export_types/csv/tsconfig.json @@ -0,0 +1,31 @@ +{ + "extends": "../../../../tsconfig.base.json", + "compilerOptions": { + "outDir": "target/types", + "types": [ + "jest", + "node", + "react" + ] + }, + "include": [ + "**/*.ts", + "**/*.tsx", + ], + "exclude": [ + "target/**/*" + ], + "kbn_references": [ + "@kbn/core", + "@kbn/reporting-common", + "@kbn/discover-plugin", + "@kbn/data-plugin", + "@kbn/generate-csv", + "@kbn/core-http-server", + "@kbn/reporting-server", + "@kbn/reporting-export-types-csv-common", + "@kbn/reporting-mocks-server", + "@kbn/core-http-request-handler-context-server", + "@kbn/field-formats-plugin", + ] +} diff --git a/packages/kbn-reporting/export_types/csv/types.ts b/packages/kbn-reporting/export_types/csv/types.ts new file mode 100644 index 0000000000000..7d06b67f61381 --- /dev/null +++ b/packages/kbn-reporting/export_types/csv/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 and the Server Side Public License, v 1; you may 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 { CustomRequestHandlerContext } from '@kbn/core-http-request-handler-context-server'; +import { ReportingServerPluginSetup } from '@kbn/reporting-server'; + +/** + * Needed because of CsvSearchSourceImmediateExportType + * @internal + */ +export type ReportingRequestHandlerContext = CustomRequestHandlerContext<{ + reporting: ReportingServerPluginSetup | null; +}>; diff --git a/packages/kbn-reporting/export_types/csv_common/README.md b/packages/kbn-reporting/export_types/csv_common/README.md new file mode 100644 index 0000000000000..c74e390257a69 --- /dev/null +++ b/packages/kbn-reporting/export_types/csv_common/README.md @@ -0,0 +1,3 @@ +# @kbn/reporting-export-types-csv-common + +Empty package generated by @kbn/generate diff --git a/src/plugins/embeddable/public/services.ts b/packages/kbn-reporting/export_types/csv_common/constants.ts similarity index 63% rename from src/plugins/embeddable/public/services.ts rename to packages/kbn-reporting/export_types/csv_common/constants.ts index 60c4b81311960..d6db2a8c635e2 100644 --- a/src/plugins/embeddable/public/services.ts +++ b/packages/kbn-reporting/export_types/csv_common/constants.ts @@ -6,7 +6,8 @@ * Side Public License, v 1. */ -import { ThemeServiceSetup } from '@kbn/core/public'; -import { createGetterSetter } from '@kbn/kibana-utils-plugin/public'; +export const CSV_JOB_TYPE = 'csv_searchsource'; +export const CSV_REPORT_TYPE = 'csv_searchsource'; -export const [getTheme, setTheme] = createGetterSetter('Theme'); +export const CSV_JOB_TYPE_V2 = 'csv_v2'; +export const CSV_REPORT_TYPE_V2 = 'csv_v2'; diff --git a/packages/kbn-reporting/export_types/csv_common/index.ts b/packages/kbn-reporting/export_types/csv_common/index.ts new file mode 100644 index 0000000000000..d15efb06e3682 --- /dev/null +++ b/packages/kbn-reporting/export_types/csv_common/index.ts @@ -0,0 +1,53 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import type { SerializedSearchSourceFields } from '@kbn/data-plugin/public'; +import type { + BaseParams, + BaseParamsV2, + BasePayload, + BasePayloadV2, +} from '@kbn/reporting-common/types'; + +export * from './constants'; + +export interface JobParamsDownloadCSV { + browserTimezone: string; + title: string; + searchSource: SerializedSearchSourceFields; + columns?: string[]; +} + +interface BaseParamsCSV { + searchSource: SerializedSearchSourceFields; + columns?: string[]; +} + +export type JobParamsCSV = BaseParamsCSV & BaseParams; +export type TaskPayloadCSV = BaseParamsCSV & BasePayload; + +interface CsvFromSavedObjectBase { + objectType: 'search'; +} + +/** + * Makes title optional, as it can be derived from the saved search object + */ +export type JobParamsCsvFromSavedObject = CsvFromSavedObjectBase & + Omit & { title?: string }; + +export type TaskPayloadCsvFromSavedObject = CsvFromSavedObjectBase & BasePayloadV2; + +export const CSV_REPORTING_ACTION = 'downloadCsvReport'; + +export const CSV_SEARCHSOURCE_IMMEDIATE_TYPE = 'csv_searchsource_immediate'; + +// This is deprecated because it lacks support for runtime fields +// but the extension points are still needed for pre-existing scripted automation, until 8.0 +export const CSV_REPORT_TYPE_DEPRECATED = 'CSV'; +export const CSV_JOB_TYPE_DEPRECATED = 'csv'; diff --git a/packages/kbn-reporting/export_types/csv_common/kibana.jsonc b/packages/kbn-reporting/export_types/csv_common/kibana.jsonc new file mode 100644 index 0000000000000..10e347c55ab5e --- /dev/null +++ b/packages/kbn-reporting/export_types/csv_common/kibana.jsonc @@ -0,0 +1,5 @@ +{ + "type": "shared-common", + "id": "@kbn/reporting-export-types-csv-common", + "owner": "@elastic/appex-sharedux" +} diff --git a/packages/kbn-reporting/export_types/csv_common/package.json b/packages/kbn-reporting/export_types/csv_common/package.json new file mode 100644 index 0000000000000..c1785bca2b208 --- /dev/null +++ b/packages/kbn-reporting/export_types/csv_common/package.json @@ -0,0 +1,6 @@ +{ + "name": "@kbn/reporting-export-types-csv-common", + "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/kbn-generate-csv-types/tsconfig.json b/packages/kbn-reporting/export_types/csv_common/tsconfig.json similarity index 75% rename from packages/kbn-generate-csv-types/tsconfig.json rename to packages/kbn-reporting/export_types/csv_common/tsconfig.json index a6242129ed177..27592ed3e537f 100644 --- a/packages/kbn-generate-csv-types/tsconfig.json +++ b/packages/kbn-reporting/export_types/csv_common/tsconfig.json @@ -1,5 +1,5 @@ { - "extends": "../../tsconfig.base.json", + "extends": "../../../../tsconfig.base.json", "compilerOptions": { "outDir": "target/types", "types": [ @@ -14,7 +14,7 @@ "target/**/*" ], "kbn_references": [ - "@kbn/config-schema", "@kbn/data-plugin", + "@kbn/reporting-common", ] } diff --git a/x-pack/plugins/reporting/server/export_types/printable_pdf/lib/generate_pdf.ts b/packages/kbn-reporting/export_types/pdf/generate_pdf.ts similarity index 67% rename from x-pack/plugins/reporting/server/export_types/printable_pdf/lib/generate_pdf.ts rename to packages/kbn-reporting/export_types/pdf/generate_pdf.ts index e5c19292ab73d..5703e16e48abc 100644 --- a/x-pack/plugins/reporting/server/export_types/printable_pdf/lib/generate_pdf.ts +++ b/packages/kbn-reporting/export_types/pdf/generate_pdf.ts @@ -1,29 +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. + * 2.0 and the Server Side Public License, v 1; you may 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 Rx from 'rxjs'; +import { Observable } from 'rxjs'; import { mergeMap, tap } from 'rxjs/operators'; -import { PdfScreenshotResult } from '@kbn/screenshotting-plugin/server'; -import { PdfScreenshotOptions } from '../../../types'; -import type { PdfMetrics } from '../../../../common/types'; -import { getTracker } from '../../common/pdf_tracker'; + +import type { PdfScreenshotOptions, PdfScreenshotResult } from '@kbn/screenshotting-plugin/server'; +import { getTracker } from './pdf_tracker'; interface PdfResult { buffer: Uint8Array | null; - metrics?: PdfMetrics; + metrics?: PdfScreenshotResult['metrics']; warnings: string[]; } -type GetScreenshotsFn = (options: PdfScreenshotOptions) => Rx.Observable; +type GetScreenshotsFn = (options: PdfScreenshotOptions) => Observable; export function generatePdfObservable( getScreenshots: GetScreenshotsFn, options: PdfScreenshotOptions -): Rx.Observable { +): Observable { const tracker = getTracker(); tracker.startScreenshots(); diff --git a/x-pack/plugins/reporting/server/export_types/printable_pdf_v2/lib/generate_pdf.ts b/packages/kbn-reporting/export_types/pdf/generate_pdf_v2.ts similarity index 60% rename from x-pack/plugins/reporting/server/export_types/printable_pdf_v2/lib/generate_pdf.ts rename to packages/kbn-reporting/export_types/pdf/generate_pdf_v2.ts index 7ab96553f3cd8..54489c6258bd8 100644 --- a/x-pack/plugins/reporting/server/export_types/printable_pdf_v2/lib/generate_pdf.ts +++ b/packages/kbn-reporting/export_types/pdf/generate_pdf_v2.ts @@ -1,37 +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. + * 2.0 and the Server Side Public License, v 1; you may 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 Rx from 'rxjs'; +import { Observable } from 'rxjs'; import { mergeMap, tap } from 'rxjs/operators'; -import { PdfScreenshotResult } from '@kbn/screenshotting-plugin/server'; -import { TaskPayloadPDFV2 } from '../../../../common/types/export_types/printable_pdf_v2'; -import { ReportingServerInfo } from '../../../core'; -import { ReportingConfigType } from '../../../config'; -import type { LocatorParams, PdfMetrics, UrlOrUrlLocatorTuple } from '../../../../common/types'; -import type { PdfScreenshotOptions } from '../../../types'; -import { getFullRedirectAppUrl } from '../../common/v2/get_full_redirect_app_url'; -import { getTracker } from '../../common/pdf_tracker'; + +import type { LocatorParams, ReportingServerInfo } from '@kbn/reporting-common/types'; +import type { TaskPayloadPDFV2 } from '@kbn/reporting-export-types-pdf-common'; +import type { PdfScreenshotOptions, PdfScreenshotResult } from '@kbn/screenshotting-plugin/server'; +import type { UrlOrUrlWithContext } from '@kbn/screenshotting-plugin/server/screenshots'; +import { type ReportingConfigType, getFullRedirectAppUrl } from '@kbn/reporting-server'; + +import { getTracker } from './pdf_tracker'; interface PdfResult { buffer: Uint8Array | null; - metrics?: PdfMetrics; + metrics?: PdfScreenshotResult['metrics']; warnings: string[]; } -type GetScreenshotsFn = (options: PdfScreenshotOptions) => Rx.Observable; +type GetScreenshotsFn = (options: PdfScreenshotOptions) => Observable; -export function generatePdfObservable( +export function generatePdfObservableV2( config: ReportingConfigType, serverInfo: ReportingServerInfo, getScreenshots: GetScreenshotsFn, job: TaskPayloadPDFV2, locatorParams: LocatorParams[], options: Omit -): Rx.Observable { +): Observable { const tracker = getTracker(); tracker.startScreenshots(); @@ -41,7 +42,8 @@ export function generatePdfObservable( const urls = locatorParams.map((locator) => [ getFullRedirectAppUrl(config, serverInfo, job.spaceId, job.forceNow), locator, - ]) as UrlOrUrlLocatorTuple[]; + ]) as unknown as UrlOrUrlWithContext[]; + const screenshots$ = getScreenshots({ ...options, urls }).pipe( tap(({ metrics }) => { if (metrics.cpu) { diff --git a/x-pack/plugins/reporting/server/export_types/common/get_absolute_url.test.ts b/packages/kbn-reporting/export_types/pdf/get_absolute_url.test.ts similarity index 93% rename from x-pack/plugins/reporting/server/export_types/common/get_absolute_url.test.ts rename to packages/kbn-reporting/export_types/pdf/get_absolute_url.test.ts index 9126660c9446a..8531bf241b268 100644 --- a/x-pack/plugins/reporting/server/export_types/common/get_absolute_url.test.ts +++ b/packages/kbn-reporting/export_types/pdf/get_absolute_url.test.ts @@ -1,8 +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. + * 2.0 and the Server Side Public License, v 1; you may 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 { getAbsoluteUrlFactory } from './get_absolute_url'; diff --git a/x-pack/plugins/reporting/server/export_types/common/get_absolute_url.ts b/packages/kbn-reporting/export_types/pdf/get_absolute_url.ts similarity index 77% rename from x-pack/plugins/reporting/server/export_types/common/get_absolute_url.ts rename to packages/kbn-reporting/export_types/pdf/get_absolute_url.ts index 9f2645fd67613..0077b43d817cf 100644 --- a/x-pack/plugins/reporting/server/export_types/common/get_absolute_url.ts +++ b/packages/kbn-reporting/export_types/pdf/get_absolute_url.ts @@ -1,8 +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. + * 2.0 and the Server Side Public License, v 1; you may 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 url from 'url'; diff --git a/x-pack/plugins/reporting/server/export_types/common/get_custom_logo.test.ts b/packages/kbn-reporting/export_types/pdf/get_custom_logo.test.ts similarity index 84% rename from x-pack/plugins/reporting/server/export_types/common/get_custom_logo.test.ts rename to packages/kbn-reporting/export_types/pdf/get_custom_logo.test.ts index 5782bf71c65b1..2fe93289414e4 100644 --- a/x-pack/plugins/reporting/server/export_types/common/get_custom_logo.test.ts +++ b/packages/kbn-reporting/export_types/pdf/get_custom_logo.test.ts @@ -1,8 +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. + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. */ import { coreMock, httpServerMock } from '@kbn/core/server/mocks'; diff --git a/x-pack/plugins/reporting/server/export_types/common/get_custom_logo.ts b/packages/kbn-reporting/export_types/pdf/get_custom_logo.ts similarity index 74% rename from x-pack/plugins/reporting/server/export_types/common/get_custom_logo.ts rename to packages/kbn-reporting/export_types/pdf/get_custom_logo.ts index a27c93c538b6f..3229a7bd2422b 100644 --- a/x-pack/plugins/reporting/server/export_types/common/get_custom_logo.ts +++ b/packages/kbn-reporting/export_types/pdf/get_custom_logo.ts @@ -1,8 +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. + * 2.0 and the Server Side Public License, v 1; you may 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 { Headers, IUiSettingsClient } from '@kbn/core/server'; diff --git a/x-pack/plugins/reporting/server/export_types/common/get_full_urls.test.ts b/packages/kbn-reporting/export_types/pdf/get_full_urls.test.ts similarity index 91% rename from x-pack/plugins/reporting/server/export_types/common/get_full_urls.test.ts rename to packages/kbn-reporting/export_types/pdf/get_full_urls.test.ts index 4621758e47a0e..46a4293a26b37 100644 --- a/x-pack/plugins/reporting/server/export_types/common/get_full_urls.test.ts +++ b/packages/kbn-reporting/export_types/pdf/get_full_urls.test.ts @@ -1,17 +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. + * 2.0 and the Server Side Public License, v 1; you may 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 { ReportingServerInfo } from '../../core'; -import { TaskPayloadPDF } from '../printable_pdf/types'; +import type { ReportingServerInfo } from '@kbn/reporting-common/types'; +import type { TaskPayloadPDF } from '@kbn/reporting-export-types-pdf-common'; +import { createMockConfigSchema } from '@kbn/reporting-mocks-server'; + import { getFullUrls } from './get_full_urls'; -import { ReportingConfigType } from '../../config'; const getMockJob = (base: object) => base as TaskPayloadPDF; -const mockConfig = { kibanaServer: {} } as unknown as ReportingConfigType; +const mockConfig = createMockConfigSchema(); const mockServerInfo: ReportingServerInfo = { hostname: 'localhost', protocol: 'http', diff --git a/x-pack/plugins/reporting/server/export_types/common/get_full_urls.ts b/packages/kbn-reporting/export_types/pdf/get_full_urls.ts similarity index 85% rename from x-pack/plugins/reporting/server/export_types/common/get_full_urls.ts rename to packages/kbn-reporting/export_types/pdf/get_full_urls.ts index 05b74d43c1bf4..a744295cbd0b4 100644 --- a/x-pack/plugins/reporting/server/export_types/common/get_full_urls.ts +++ b/packages/kbn-reporting/export_types/pdf/get_full_urls.ts @@ -1,8 +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. + * 2.0 and the Server Side Public License, v 1; you may 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 { @@ -11,9 +12,11 @@ import { UrlWithParsedQuery, UrlWithStringQuery, } from 'url'; -import { ReportingConfigType } from '../../config'; -import { ReportingServerInfo } from '../../core'; -import { TaskPayloadPDF } from '../printable_pdf/types'; + +import type { ReportingServerInfo } from '@kbn/reporting-common/types'; +import type { TaskPayloadPDF } from '@kbn/reporting-export-types-pdf-common'; +import type { ReportingConfigType } from '@kbn/reporting-server'; + import { getAbsoluteUrlFactory } from './get_absolute_url'; import { validateUrls } from './validate_urls'; @@ -44,7 +47,7 @@ export function getFullUrls( validateUrls(relativeUrls); const urls = relativeUrls.map((relativeUrl) => { - const parsedRelative: UrlWithStringQuery = urlParse(relativeUrl); // FIXME: '(urlStr: string): UrlWithStringQuery' is deprecated + const parsedRelative: UrlWithStringQuery = urlParse(relativeUrl); const jobUrl = getAbsoluteUrl({ path: parsedRelative.pathname === null ? undefined : parsedRelative.pathname, hash: parsedRelative.hash === null ? undefined : parsedRelative.hash, diff --git a/packages/kbn-reporting/export_types/pdf/index.ts b/packages/kbn-reporting/export_types/pdf/index.ts new file mode 100644 index 0000000000000..e4ce328f9026e --- /dev/null +++ b/packages/kbn-reporting/export_types/pdf/index.ts @@ -0,0 +1,10 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +export { PdfExportType } from './printable_pdf_v2'; +export { PdfV1ExportType } from './printable_pdf'; diff --git a/packages/kbn-reporting/export_types/pdf/jest.config.js b/packages/kbn-reporting/export_types/pdf/jest.config.js new file mode 100644 index 0000000000000..eb1d1bff052d0 --- /dev/null +++ b/packages/kbn-reporting/export_types/pdf/jest.config.js @@ -0,0 +1,13 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +module.exports = { + preset: '@kbn/test/jest_node', + rootDir: '../../../..', + roots: ['/packages/kbn-reporting/export_types/pdf'], +}; diff --git a/packages/kbn-reporting/export_types/pdf/kibana.jsonc b/packages/kbn-reporting/export_types/pdf/kibana.jsonc new file mode 100644 index 0000000000000..1cc83f4395e21 --- /dev/null +++ b/packages/kbn-reporting/export_types/pdf/kibana.jsonc @@ -0,0 +1,5 @@ +{ + "type": "shared-server", + "id": "@kbn/reporting-export-types-pdf", + "owner": "@elastic/appex-sharedux" + } \ No newline at end of file diff --git a/packages/kbn-reporting/export_types/pdf/package.json b/packages/kbn-reporting/export_types/pdf/package.json new file mode 100644 index 0000000000000..d894a03ff7b56 --- /dev/null +++ b/packages/kbn-reporting/export_types/pdf/package.json @@ -0,0 +1,6 @@ +{ + "name": "@kbn/reporting-export-types-pdf", + "private": true, + "version": "1.0.0", + "license": "SSPL-1.0 OR Elastic License 2.0" + } \ No newline at end of file diff --git a/x-pack/plugins/reporting/server/export_types/common/pdf_tracker.ts b/packages/kbn-reporting/export_types/pdf/pdf_tracker.ts similarity index 85% rename from x-pack/plugins/reporting/server/export_types/common/pdf_tracker.ts rename to packages/kbn-reporting/export_types/pdf/pdf_tracker.ts index 80d1776f994f3..0af96118d993b 100644 --- a/x-pack/plugins/reporting/server/export_types/common/pdf_tracker.ts +++ b/packages/kbn-reporting/export_types/pdf/pdf_tracker.ts @@ -1,8 +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. + * 2.0 and the Server Side Public License, v 1; you may 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 apm from 'elastic-apm-node'; diff --git a/x-pack/plugins/reporting/server/export_types/printable_pdf/printable_pdf.test.ts b/packages/kbn-reporting/export_types/pdf/printable_pdf.test.ts similarity index 76% rename from x-pack/plugins/reporting/server/export_types/printable_pdf/printable_pdf.test.ts rename to packages/kbn-reporting/export_types/pdf/printable_pdf.test.ts index 32e0bc3e9b921..9ca0fa34effcd 100644 --- a/x-pack/plugins/reporting/server/export_types/printable_pdf/printable_pdf.test.ts +++ b/packages/kbn-reporting/export_types/pdf/printable_pdf.test.ts @@ -1,31 +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. + * 2.0 and the Server Side Public License, v 1; you may 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 Rx from 'rxjs'; -import { coreMock, elasticsearchServiceMock, loggingSystemMock } from '@kbn/core/server/mocks'; +import { of } from 'rxjs'; import { Writable } from 'stream'; + +import { coreMock, elasticsearchServiceMock, loggingSystemMock } from '@kbn/core/server/mocks'; import { CancellationToken } from '@kbn/reporting-common'; -import { generatePdfObservable } from './lib/generate_pdf'; -import { cryptoFactory } from '../../lib/crypto'; -import { TaskPayloadPDF } from './types'; -import { PdfV1ExportType } from './printable_pdf'; +import { TaskPayloadPDF } from '@kbn/reporting-export-types-pdf-common'; +import { createMockConfigSchema } from '@kbn/reporting-mocks-server'; +import { cryptoFactory } from '@kbn/reporting-server'; import { ScreenshottingStart } from '@kbn/screenshotting-plugin/server'; -import { createMockConfigSchema, createMockReportingCore } from '../../test_helpers'; -jest.mock('./lib/generate_pdf'); +import { PdfV1ExportType } from '.'; +import { generatePdfObservable } from './generate_pdf'; + +jest.mock('./generate_pdf'); let content: string; let mockPdfExportType: PdfV1ExportType; let stream: jest.Mocked; -const cancellationToken = { - on: jest.fn(), -} as unknown as CancellationToken; - +const cancellationToken = new CancellationToken(); const mockLogger = loggingSystemMock.createLogger(); const mockEncryptionKey = 'testencryptionkey'; @@ -44,7 +44,6 @@ beforeEach(async () => { const mockCoreSetup = coreMock.createSetup(); const mockCoreStart = coreMock.createStart(); - const mockReportingCore = await createMockReportingCore(createMockConfigSchema()); mockPdfExportType = new PdfV1ExportType(mockCoreSetup, configType, mockLogger, context); @@ -56,7 +55,6 @@ beforeEach(async () => { savedObjects: mockCoreStart.savedObjects, uiSettings: mockCoreStart.uiSettings, screenshotting: {} as unknown as ScreenshottingStart, - reporting: mockReportingCore.getContract(), }); }); @@ -64,7 +62,7 @@ afterEach(() => (generatePdfObservable as jest.Mock).mockReset()); test(`passes browserTimezone to generatePdf`, async () => { const encryptedHeaders = await encryptHeaders({}); - (generatePdfObservable as jest.Mock).mockReturnValue(Rx.of({ buffer: Buffer.from('') })); + (generatePdfObservable as jest.Mock).mockReturnValue(of({ buffer: Buffer.from('') })); const browserTimezone = 'UTC'; await mockPdfExportType.runTask( @@ -87,7 +85,7 @@ test(`passes browserTimezone to generatePdf`, async () => { test(`returns content_type of application/pdf`, async () => { const encryptedHeaders = await encryptHeaders({}); - (generatePdfObservable as jest.Mock).mockReturnValue(Rx.of({ buffer: Buffer.from('') })); + (generatePdfObservable as jest.Mock).mockReturnValue(of({ buffer: Buffer.from('') })); const { content_type: contentType } = await mockPdfExportType.runTask( 'pdfJobId', @@ -100,7 +98,7 @@ test(`returns content_type of application/pdf`, async () => { test(`returns content of generatePdf getBuffer base64 encoded`, async () => { const testContent = 'test content'; - (generatePdfObservable as jest.Mock).mockReturnValue(Rx.of({ buffer: Buffer.from(testContent) })); + (generatePdfObservable as jest.Mock).mockReturnValue(of({ buffer: Buffer.from(testContent) })); const encryptedHeaders = await encryptHeaders({}); await mockPdfExportType.runTask( diff --git a/x-pack/plugins/reporting/server/export_types/printable_pdf/printable_pdf.ts b/packages/kbn-reporting/export_types/pdf/printable_pdf.ts similarity index 73% rename from x-pack/plugins/reporting/server/export_types/printable_pdf/printable_pdf.ts rename to packages/kbn-reporting/export_types/pdf/printable_pdf.ts index 85e656642eb62..6c8ce2a5b1d0d 100644 --- a/x-pack/plugins/reporting/server/export_types/printable_pdf/printable_pdf.ts +++ b/packages/kbn-reporting/export_types/pdf/printable_pdf.ts @@ -1,30 +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. + * 2.0 and the Server Side Public License, v 1; you may 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 { LicenseType } from '@kbn/licensing-plugin/server'; -import { CancellationToken, TaskRunResult } from '@kbn/reporting-common'; -import { Writable } from 'stream'; import apm from 'elastic-apm-node'; +import { Observable, fromEventPattern, lastValueFrom, of, throwError } from 'rxjs'; import { catchError, map, mergeMap, takeUntil, tap } from 'rxjs/operators'; -import { fromEventPattern, lastValueFrom, Observable, of, throwError } from 'rxjs'; -import { JobParamsPDFDeprecated } from '../../../common/types'; +import { Writable } from 'stream'; + +import type { LicenseType } from '@kbn/licensing-plugin/server'; import { + CancellationToken, LICENSE_TYPE_CLOUD_STANDARD, LICENSE_TYPE_ENTERPRISE, LICENSE_TYPE_GOLD, LICENSE_TYPE_PLATINUM, LICENSE_TYPE_TRIAL, - PDF_JOB_TYPE, REPORTING_TRANSACTION_TYPE, -} from '../../../common/constants'; -import { decryptJobHeaders, ExportType, getCustomLogo, getFullUrls, validateUrls } from '../common'; -import { TaskPayloadPDF } from './types'; -import { generatePdfObservable } from './lib/generate_pdf'; +} from '@kbn/reporting-common'; +import { TaskRunResult } from '@kbn/reporting-common/types'; +import { + JobParamsPDFDeprecated, + PDF_JOB_TYPE, + TaskPayloadPDF, +} from '@kbn/reporting-export-types-pdf-common'; +import { ExportType, decryptJobHeaders } from '@kbn/reporting-server'; + +import { generatePdfObservable } from './generate_pdf'; +import { validateUrls } from './validate_urls'; +import { getCustomLogo } from './get_custom_logo'; +import { getFullUrls } from './get_full_urls'; +/** + * @deprecated + */ export class PdfV1ExportType extends ExportType { id = 'printablePdf'; name = 'PDF'; @@ -83,9 +95,19 @@ export class PdfV1ExportType extends ExportType - this.startDeps.reporting.getScreenshots!({ + + return generatePdfObservable( + () => + this.startDeps.screenshotting!.getScreenshots({ + format: 'pdf', + title, + logo, + urls, + browserTimezone, + headers, + layout, + }), + { format: 'pdf', title, logo, @@ -93,16 +115,8 @@ export class PdfV1ExportType extends ExportType { apmGeneratePdf?.end(); diff --git a/x-pack/plugins/reporting/server/export_types/printable_pdf_v2/printable_pdf_v2.test.ts b/packages/kbn-reporting/export_types/pdf/printable_pdf_v2.test.ts similarity index 74% rename from x-pack/plugins/reporting/server/export_types/printable_pdf_v2/printable_pdf_v2.test.ts rename to packages/kbn-reporting/export_types/pdf/printable_pdf_v2.test.ts index fd6e6ace45d8f..4e4f0c1491130 100644 --- a/x-pack/plugins/reporting/server/export_types/printable_pdf_v2/printable_pdf_v2.test.ts +++ b/packages/kbn-reporting/export_types/pdf/printable_pdf_v2.test.ts @@ -1,32 +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. + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. */ -jest.mock('./lib/generate_pdf'); +import { of } from 'rxjs'; +import type { Writable } from 'stream'; import { coreMock, elasticsearchServiceMock, loggingSystemMock } from '@kbn/core/server/mocks'; import { CancellationToken } from '@kbn/reporting-common'; +import type { LocatorParams } from '@kbn/reporting-common/types'; +import type { TaskPayloadPDFV2 } from '@kbn/reporting-export-types-pdf-common'; +import { createMockConfigSchema } from '@kbn/reporting-mocks-server'; +import { cryptoFactory } from '@kbn/reporting-server'; import type { ScreenshottingStart } from '@kbn/screenshotting-plugin/server'; -import * as Rx from 'rxjs'; -import type { Writable } from 'stream'; + import { PdfExportType } from '.'; -import type { LocatorParams } from '../../../common'; -import type { TaskPayloadPDFV2 } from '../../../common/types/export_types/printable_pdf_v2'; -import { cryptoFactory } from '../../lib'; -import { generatePdfObservable } from './lib/generate_pdf'; -import { createMockConfigSchema, createMockReportingCore } from '../../test_helpers'; +import { generatePdfObservableV2 } from './generate_pdf_v2'; + +jest.mock('./generate_pdf_v2'); let content: string; let mockPdfExportType: PdfExportType; let stream: jest.Mocked; -const cancellationToken = { - on: jest.fn(), -} as unknown as CancellationToken; - +const cancellationToken = new CancellationToken(); const mockLogger = loggingSystemMock.createLogger(); const mockEncryptionKey = 'testencryptionkey'; @@ -50,8 +50,6 @@ beforeEach(async () => { const mockCoreSetup = coreMock.createSetup(); const mockCoreStart = coreMock.createStart(); - const mockReportingCore = await createMockReportingCore(createMockConfigSchema()); - mockPdfExportType = new PdfExportType(mockCoreSetup, configType, mockLogger, context); mockPdfExportType.setup({ @@ -62,15 +60,14 @@ beforeEach(async () => { savedObjects: mockCoreStart.savedObjects, uiSettings: mockCoreStart.uiSettings, screenshotting: {} as unknown as ScreenshottingStart, - reporting: mockReportingCore.getContract(), }); }); -afterEach(() => (generatePdfObservable as jest.Mock).mockReset()); +afterEach(() => (generatePdfObservableV2 as jest.Mock).mockReset()); test(`passes browserTimezone to generatePdf`, async () => { const encryptedHeaders = await encryptHeaders({}); - (generatePdfObservable as jest.Mock).mockReturnValue(Rx.of(Buffer.from(''))); + (generatePdfObservableV2 as jest.Mock).mockReturnValue(of(Buffer.from(''))); const browserTimezone = 'UTC'; await mockPdfExportType.runTask( @@ -86,7 +83,7 @@ test(`passes browserTimezone to generatePdf`, async () => { stream ); - expect(generatePdfObservable).toHaveBeenCalledWith( + expect(generatePdfObservableV2).toHaveBeenCalledWith( expect.anything(), expect.anything(), expect.anything(), @@ -99,7 +96,7 @@ test(`passes browserTimezone to generatePdf`, async () => { test(`returns content_type of application/pdf`, async () => { const encryptedHeaders = await encryptHeaders({}); - (generatePdfObservable as jest.Mock).mockReturnValue(Rx.of({ buffer: Buffer.from('') })); + (generatePdfObservableV2 as jest.Mock).mockReturnValue(of({ buffer: Buffer.from('') })); const { content_type: contentType } = await mockPdfExportType.runTask( 'pdfJobId', @@ -112,7 +109,7 @@ test(`returns content_type of application/pdf`, async () => { test(`returns content of generatePdf getBuffer base64 encoded`, async () => { const testContent = 'test content'; - (generatePdfObservable as jest.Mock).mockReturnValue(Rx.of({ buffer: Buffer.from(testContent) })); + (generatePdfObservableV2 as jest.Mock).mockReturnValue(of({ buffer: Buffer.from(testContent) })); const encryptedHeaders = await encryptHeaders({}); await mockPdfExportType.runTask( diff --git a/x-pack/plugins/reporting/server/export_types/printable_pdf_v2/printable_pdf_v2.ts b/packages/kbn-reporting/export_types/pdf/printable_pdf_v2.ts similarity index 77% rename from x-pack/plugins/reporting/server/export_types/printable_pdf_v2/printable_pdf_v2.ts rename to packages/kbn-reporting/export_types/pdf/printable_pdf_v2.ts index 862d5908ddb3c..cc975c536803d 100644 --- a/x-pack/plugins/reporting/server/export_types/printable_pdf_v2/printable_pdf_v2.ts +++ b/packages/kbn-reporting/export_types/pdf/printable_pdf_v2.ts @@ -1,31 +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. + * 2.0 and the Server Side Public License, v 1; you may 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 { Headers } from '@kbn/core/server'; -import { CancellationToken, TaskRunResult } from '@kbn/reporting-common'; import apm from 'elastic-apm-node'; import * as Rx from 'rxjs'; -import { catchError, map, mergeMap, takeUntil, tap } from 'rxjs'; +import { catchError, map, mergeMap, of, takeUntil, tap } from 'rxjs'; import { Writable } from 'stream'; + +import { Headers } from '@kbn/core/server'; import { + CancellationToken, LICENSE_TYPE_CLOUD_STANDARD, LICENSE_TYPE_ENTERPRISE, LICENSE_TYPE_GOLD, LICENSE_TYPE_PLATINUM, LICENSE_TYPE_TRIAL, + REPORTING_REDIRECT_LOCATOR_STORE_KEY, + REPORTING_TRANSACTION_TYPE, +} from '@kbn/reporting-common'; +import type { TaskRunResult, UrlOrUrlLocatorTuple } from '@kbn/reporting-common/types'; +import { + JobParamsPDFV2, PDF_JOB_TYPE_V2, PDF_REPORT_TYPE_V2, - REPORTING_TRANSACTION_TYPE, -} from '../../../common/constants'; -import { JobParamsPDFV2, UrlOrUrlLocatorTuple } from '../../../common/types'; -import { TaskPayloadPDFV2 } from '../../../common/types/export_types/printable_pdf_v2'; -import { decryptJobHeaders, ExportType, getCustomLogo } from '../common'; -import { getFullRedirectAppUrl } from '../common/v2/get_full_redirect_app_url'; -import { generatePdfObservable } from './lib/generate_pdf'; + TaskPayloadPDFV2, +} from '@kbn/reporting-export-types-pdf-common'; +import { decryptJobHeaders, getFullRedirectAppUrl, ExportType } from '@kbn/reporting-server'; + +import { generatePdfObservableV2 } from './generate_pdf_v2'; +import { getCustomLogo } from './get_custom_logo'; export class PdfExportType extends ExportType { id = PDF_REPORT_TYPE_V2; @@ -79,7 +86,7 @@ export class PdfExportType extends ExportType let apmGeneratePdf: { end: () => void } | null | undefined; const { encryptionKey } = this.config; - const process$: Rx.Observable = Rx.of(1).pipe( + const process$: Rx.Observable = of(1).pipe( mergeMap(() => decryptJobHeaders(encryptionKey, payload.headers, jobLogger)), mergeMap(async (headers: Headers) => { const fakeRequest = this.getFakeRequest(headers, payload.spaceId, jobLogger); @@ -98,24 +105,29 @@ export class PdfExportType extends ExportType payload.forceNow ), locator, - ]) as unknown as UrlOrUrlLocatorTuple[]; + ]); } apmGetAssets?.end(); apmGeneratePdf = apmTrans.startSpan('generate-pdf-pipeline', 'execute'); - return generatePdfObservable( + + return generatePdfObservableV2( this.config, this.getServerInfo(), () => - this.startDeps.reporting.getScreenshots!({ + this.startDeps.screenshotting!.getScreenshots({ format: 'pdf', title, logo, browserTimezone, headers, layout, - urls, + urls: urls.map((url) => + typeof url === 'string' + ? url + : [url[0], { [REPORTING_REDIRECT_LOCATOR_STORE_KEY]: url[1] }] + ), }), payload, locatorParams, diff --git a/packages/kbn-reporting/export_types/pdf/tsconfig.json b/packages/kbn-reporting/export_types/pdf/tsconfig.json new file mode 100644 index 0000000000000..9f778e9cef3bf --- /dev/null +++ b/packages/kbn-reporting/export_types/pdf/tsconfig.json @@ -0,0 +1,26 @@ +{ + "extends": "../../../../tsconfig.base.json", + "compilerOptions": { + "outDir": "target/types", + "types": [ + "jest", + "node", + ] + }, + "include": [ + "**/*.ts", + "**/*.tsx", + ], + "exclude": [ + "target/**/*" + ], + "kbn_references": [ + "@kbn/core", + "@kbn/reporting-common", + "@kbn/screenshotting-plugin", + "@kbn/reporting-server", + "@kbn/licensing-plugin", + "@kbn/reporting-export-types-pdf-common", + "@kbn/reporting-mocks-server", + ] +} diff --git a/x-pack/plugins/reporting/server/export_types/common/validate_urls.test.ts b/packages/kbn-reporting/export_types/pdf/validate_urls.test.ts similarity index 94% rename from x-pack/plugins/reporting/server/export_types/common/validate_urls.test.ts rename to packages/kbn-reporting/export_types/pdf/validate_urls.test.ts index c945802b8342b..65d95ddd4ed79 100644 --- a/x-pack/plugins/reporting/server/export_types/common/validate_urls.test.ts +++ b/packages/kbn-reporting/export_types/pdf/validate_urls.test.ts @@ -1,8 +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. + * 2.0 and the Server Side Public License, v 1; you may 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 { validateUrls } from './validate_urls'; diff --git a/x-pack/plugins/reporting/server/export_types/common/validate_urls.ts b/packages/kbn-reporting/export_types/pdf/validate_urls.ts similarity index 85% rename from x-pack/plugins/reporting/server/export_types/common/validate_urls.ts rename to packages/kbn-reporting/export_types/pdf/validate_urls.ts index e6d392c0bb55c..e3edb26444043 100644 --- a/x-pack/plugins/reporting/server/export_types/common/validate_urls.ts +++ b/packages/kbn-reporting/export_types/pdf/validate_urls.ts @@ -1,8 +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. + * 2.0 and the Server Side Public License, v 1; you may 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 { parse } from 'url'; diff --git a/packages/kbn-reporting/export_types/pdf_common/README.md b/packages/kbn-reporting/export_types/pdf_common/README.md new file mode 100644 index 0000000000000..24fe1383b42f0 --- /dev/null +++ b/packages/kbn-reporting/export_types/pdf_common/README.md @@ -0,0 +1,3 @@ +# @kbn/reporting-export-types-pdf-common + +Empty package generated by @kbn/generate diff --git a/packages/kbn-reporting/export_types/pdf_common/constants.ts b/packages/kbn-reporting/export_types/pdf_common/constants.ts new file mode 100644 index 0000000000000..a91a3da8602d1 --- /dev/null +++ b/packages/kbn-reporting/export_types/pdf_common/constants.ts @@ -0,0 +1,13 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may 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 PDF_JOB_TYPE = 'printable_pdf'; +export const PDF_JOB_TYPE_V2 = 'printable_pdf_v2'; + +export const PDF_REPORT_TYPE = 'printablePdf'; +export const PDF_REPORT_TYPE_V2 = 'printablePdfV2'; diff --git a/packages/kbn-reporting/export_types/pdf_common/index.ts b/packages/kbn-reporting/export_types/pdf_common/index.ts new file mode 100644 index 0000000000000..f1ff9a0d02ecf --- /dev/null +++ b/packages/kbn-reporting/export_types/pdf_common/index.ts @@ -0,0 +1,64 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import type { BaseParams, BasePayload, LocatorParams } from '@kbn/reporting-common/types'; +import { LayoutParams } from '@kbn/screenshotting-plugin/common'; + +export * from './constants'; + +/** + * Structure of stored job data provided by create_job + */ +export interface TaskPayloadPDF extends BasePayload { + layout: LayoutParams; + forceNow?: string; + objects: Array<{ relativeUrl: string }>; +} + +interface BaseParamsPDFV2 { + layout: LayoutParams; + + /** + * This value is used to re-create the same visual state as when the report was requested as well as navigate to the correct page. + */ + locatorParams: LocatorParams[]; +} + +// Job params: structure of incoming user request data, after being parsed from RISON +export type JobParamsPDFV2 = BaseParamsPDFV2 & BaseParams; + +/** + * Public-facing interface + * Apps should use this interface to build job params. + * browserTimezone and version is provided by Reporting + * @public + */ +export type JobAppParamsPDFV2 = Omit; + +// Job payload: structure of stored job data provided by create_job +export interface TaskPayloadPDFV2 extends BasePayload, BaseParamsPDFV2 { + layout: LayoutParams; + /** + * The value of forceNow is injected server-side every time a given report is generated. + */ + forceNow: string; +} + +/** + * @deprecated + */ +interface BaseParamsPDF { + layout: LayoutParams; + relativeUrls: string[]; + isDeprecated?: boolean; +} + +/** + * @deprecated + */ +export type JobParamsPDFDeprecated = BaseParamsPDF & BaseParams; diff --git a/packages/kbn-reporting/export_types/pdf_common/kibana.jsonc b/packages/kbn-reporting/export_types/pdf_common/kibana.jsonc new file mode 100644 index 0000000000000..a9aecce082861 --- /dev/null +++ b/packages/kbn-reporting/export_types/pdf_common/kibana.jsonc @@ -0,0 +1,5 @@ +{ + "type": "shared-common", + "id": "@kbn/reporting-export-types-pdf-common", + "owner": "@elastic/appex-sharedux" +} diff --git a/packages/kbn-reporting/export_types/pdf_common/package.json b/packages/kbn-reporting/export_types/pdf_common/package.json new file mode 100644 index 0000000000000..1d0dc201e4ea8 --- /dev/null +++ b/packages/kbn-reporting/export_types/pdf_common/package.json @@ -0,0 +1,6 @@ +{ + "name": "@kbn/reporting-export-types-pdf-common", + "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/kbn-reporting/export_types/pdf_common/tsconfig.json b/packages/kbn-reporting/export_types/pdf_common/tsconfig.json new file mode 100644 index 0000000000000..cb0a7b461eda8 --- /dev/null +++ b/packages/kbn-reporting/export_types/pdf_common/tsconfig.json @@ -0,0 +1,20 @@ +{ + "extends": "../../../../tsconfig.base.json", + "compilerOptions": { + "outDir": "target/types", + "types": [ + "jest", + "node" + ] + }, + "include": [ + "**/*.ts", + ], + "exclude": [ + "target/**/*" + ], + "kbn_references": [ + "@kbn/screenshotting-plugin", + "@kbn/reporting-common", + ] +} diff --git a/x-pack/plugins/reporting/server/export_types/common/generate_png.ts b/packages/kbn-reporting/export_types/png/generate_png.ts similarity index 74% rename from x-pack/plugins/reporting/server/export_types/common/generate_png.ts rename to packages/kbn-reporting/export_types/png/generate_png.ts index 7bd03c7bffdcd..d0ce9b9791690 100644 --- a/x-pack/plugins/reporting/server/export_types/common/generate_png.ts +++ b/packages/kbn-reporting/export_types/png/generate_png.ts @@ -1,32 +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. + * 2.0 and the Server Side Public License, v 1; you may 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 apm from 'elastic-apm-node'; -import type { Logger } from '@kbn/core/server'; -import * as Rx from 'rxjs'; +import { Observable } from 'rxjs'; import { finalize, map, tap } from 'rxjs/operators'; -import { PngScreenshotResult } from '@kbn/screenshotting-plugin/server'; -import { REPORTING_TRANSACTION_TYPE } from '../../../common/constants'; -import type { PngMetrics } from '../../../common/types'; -import type { PngScreenshotOptions } from '../../types'; + +import type { Logger } from '@kbn/logging'; +import { REPORTING_TRANSACTION_TYPE } from '@kbn/reporting-common/constants'; +import type { PngScreenshotOptions, PngScreenshotResult } from '@kbn/screenshotting-plugin/server'; interface PngResult { buffer: Buffer; - metrics?: PngMetrics; + metrics?: PngScreenshotResult['metrics']; warnings: string[]; } -type GetScreenshotsFn = (options: PngScreenshotOptions) => Rx.Observable; +type GetScreenshotsFn = (options: PngScreenshotOptions) => Observable; export function generatePngObservable( getScreenshots: GetScreenshotsFn, logger: Logger, options: Omit -): Rx.Observable { +): Observable { const apmTrans = apm.startTransaction('generate-png', REPORTING_TRANSACTION_TYPE); if (!options.layout?.dimensions) { throw new Error(`LayoutParams.Dimensions is undefined.`); diff --git a/src/plugins/kibana_react/public/toolbar_button/index.ts b/packages/kbn-reporting/export_types/png/index.ts similarity index 89% rename from src/plugins/kibana_react/public/toolbar_button/index.ts rename to packages/kbn-reporting/export_types/png/index.ts index af21f700901b9..551255cb5d112 100644 --- a/src/plugins/kibana_react/public/toolbar_button/index.ts +++ b/packages/kbn-reporting/export_types/png/index.ts @@ -6,4 +6,4 @@ * Side Public License, v 1. */ -export * from './toolbar_button'; +export { PngExportType } from './png_v2'; diff --git a/packages/kbn-reporting/export_types/png/jest.config.js b/packages/kbn-reporting/export_types/png/jest.config.js new file mode 100644 index 0000000000000..467708b5bfe9f --- /dev/null +++ b/packages/kbn-reporting/export_types/png/jest.config.js @@ -0,0 +1,13 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +module.exports = { + preset: '@kbn/test/jest_node', + rootDir: '../../../..', + roots: ['/packages/kbn-reporting/export_types/png'], +}; diff --git a/packages/kbn-reporting/export_types/png/kibana.jsonc b/packages/kbn-reporting/export_types/png/kibana.jsonc new file mode 100644 index 0000000000000..b8923806260fb --- /dev/null +++ b/packages/kbn-reporting/export_types/png/kibana.jsonc @@ -0,0 +1,5 @@ +{ + "type": "shared-server", + "id": "@kbn/reporting-export-types-png", + "owner": "@elastic/appex-sharedux" + } \ No newline at end of file diff --git a/packages/kbn-reporting/export_types/png/package.json b/packages/kbn-reporting/export_types/png/package.json new file mode 100644 index 0000000000000..1983ed6543944 --- /dev/null +++ b/packages/kbn-reporting/export_types/png/package.json @@ -0,0 +1,6 @@ +{ + "name": "@kbn/reporting-export-types-png", + "private": true, + "version": "1.0.0", + "license": "SSPL-1.0 OR Elastic License 2.0" + } \ No newline at end of file diff --git a/x-pack/plugins/reporting/server/export_types/png_v2/png_v2.test.ts b/packages/kbn-reporting/export_types/png/png_v2.test.ts similarity index 76% rename from x-pack/plugins/reporting/server/export_types/png_v2/png_v2.test.ts rename to packages/kbn-reporting/export_types/png/png_v2.test.ts index 8b142b7ba765a..a6cc8b1891eef 100644 --- a/x-pack/plugins/reporting/server/export_types/png_v2/png_v2.test.ts +++ b/packages/kbn-reporting/export_types/png/png_v2.test.ts @@ -1,34 +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. + * 2.0 and the Server Side Public License, v 1; you may 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 Rx from 'rxjs'; -import { coreMock, elasticsearchServiceMock, loggingSystemMock } from '@kbn/core/server/mocks'; import { Writable } from 'stream'; + +import { coreMock, elasticsearchServiceMock, loggingSystemMock } from '@kbn/core/server/mocks'; import { CancellationToken } from '@kbn/reporting-common'; -import { ScreenshottingStart } from '@kbn/screenshotting-plugin/server'; -import { ReportingCore } from '../..'; -import { LocatorParams } from '../../../common/types'; -import { cryptoFactory } from '../../lib'; -import { createMockConfigSchema, createMockReportingCore } from '../../test_helpers'; -import { generatePngObservable } from '../common'; -import { TaskPayloadPNGV2 } from './types'; -import { PngExportType } from './png_v2'; +import type { LocatorParams } from '@kbn/reporting-common/types'; +import type { TaskPayloadPNGV2 } from '@kbn/reporting-export-types-png-common'; +import { createMockConfigSchema } from '@kbn/reporting-mocks-server'; +import { cryptoFactory } from '@kbn/reporting-server'; +import type { ScreenshottingStart } from '@kbn/screenshotting-plugin/server'; -jest.mock('../common/generate_png'); +import { PngExportType } from '.'; +import { generatePngObservable } from './generate_png'; + +jest.mock('./generate_png'); let content: string; -let mockReportingCore: ReportingCore; let mockPngExportType: PngExportType; let stream: jest.Mocked; -const cancellationToken = { - on: jest.fn(), -} as unknown as CancellationToken; - +const cancellationToken = new CancellationToken(); const mockLogger = loggingSystemMock.createLogger(); const mockEncryptionKey = 'abcabcsecuresecret'; @@ -51,7 +49,6 @@ beforeEach(async () => { }, }); - mockReportingCore = await createMockReportingCore(configType); const context = coreMock.createPluginInitializerContext(configType); const mockCoreSetup = coreMock.createSetup(); @@ -66,7 +63,6 @@ beforeEach(async () => { uiSettings: mockCoreStart.uiSettings, screenshotting: {} as unknown as ScreenshottingStart, esClient: elasticsearchServiceMock.createClusterClient(), - reporting: mockReportingCore.getContract(), }); }); @@ -81,7 +77,7 @@ test(`passes browserTimezone to generatePng`, async () => { 'pngJobId', getBasePayload({ forceNow: 'test', - locatorParams: [{ version: 'test', id: 'test', params: {} }] as LocatorParams[], + locatorParams: [], browserTimezone, headers: encryptedHeaders, }), @@ -93,14 +89,9 @@ test(`passes browserTimezone to generatePng`, async () => { expect.anything(), expect.anything(), expect.objectContaining({ - urls: [ - [ - 'http://localhost:80/mock-server-basepath/app/reportingRedirect?forceNow=test', - { id: 'test', params: {}, version: 'test' }, - ], - ], browserTimezone: 'UTC', headers: {}, + layout: { id: 'preserve_layout' }, }) ); }); diff --git a/x-pack/plugins/reporting/server/export_types/png_v2/png_v2.ts b/packages/kbn-reporting/export_types/png/png_v2.ts similarity index 79% rename from x-pack/plugins/reporting/server/export_types/png_v2/png_v2.ts rename to packages/kbn-reporting/export_types/png/png_v2.ts index 6afac5dacb4cb..15f0c26d45932 100644 --- a/x-pack/plugins/reporting/server/export_types/png_v2/png_v2.ts +++ b/packages/kbn-reporting/export_types/png/png_v2.ts @@ -1,13 +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. + * 2.0 and the Server Side Public License, v 1; you may 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 apm from 'elastic-apm-node'; -import { LicenseType } from '@kbn/licensing-plugin/server'; -import { CancellationToken, TaskRunResult } from '@kbn/reporting-common'; -import { Writable } from 'stream'; import { finalize, fromEventPattern, @@ -19,21 +18,29 @@ import { takeUntil, tap, } from 'rxjs'; -import { SerializableRecord } from '@kbn/utility-types'; -import { LocatorParams } from '../../../common'; +import { Writable } from 'stream'; + +import type { LicenseType } from '@kbn/licensing-plugin/server'; import { + CancellationToken, LICENSE_TYPE_CLOUD_STANDARD, LICENSE_TYPE_ENTERPRISE, LICENSE_TYPE_GOLD, LICENSE_TYPE_PLATINUM, LICENSE_TYPE_TRIAL, + REPORTING_REDIRECT_LOCATOR_STORE_KEY, + REPORTING_TRANSACTION_TYPE, +} from '@kbn/reporting-common'; +import type { TaskRunResult } from '@kbn/reporting-common/types'; +import { + JobParamsPNGV2, PNG_JOB_TYPE_V2, PNG_REPORT_TYPE_V2, - REPORTING_TRANSACTION_TYPE, -} from '../../../common/constants'; -import { decryptJobHeaders, ExportType, generatePngObservable } from '../common'; -import { JobParamsPNGV2, TaskPayloadPNGV2 } from './types'; -import { getFullRedirectAppUrl } from '../common/v2/get_full_redirect_app_url'; + TaskPayloadPNGV2, +} from '@kbn/reporting-export-types-png-common'; +import { decryptJobHeaders, getFullRedirectAppUrl, ExportType } from '@kbn/reporting-server'; + +import { generatePngObservable } from './generate_png'; export class PngExportType extends ExportType { id = PNG_REPORT_TYPE_V2; @@ -61,7 +68,7 @@ export class PngExportType extends ExportType public createJob = async ({ locatorParams, ...jobParams }: JobParamsPNGV2) => { return { ...jobParams, - locatorParams: [locatorParams] as unknown as LocatorParams, + locatorParams: [locatorParams], isDeprecated: false, browserTimezone: jobParams.browserTimezone, forceNow: new Date().toISOString(), @@ -104,18 +111,17 @@ export class PngExportType extends ExportType return generatePngObservable( () => - this.startDeps.reporting.getScreenshots!({ + this.startDeps.screenshotting!.getScreenshots({ format: 'png', headers, layout: { ...payload.layout, id: 'preserve_layout' }, - urls: [[url, locatorParams]], + urls: [[url, { [REPORTING_REDIRECT_LOCATOR_STORE_KEY]: locatorParams }]], }), jobLogger, { headers, browserTimezone: payload.browserTimezone, layout: { ...payload.layout, id: 'preserve_layout' }, - urls: [[url, locatorParams]], } ); }), diff --git a/packages/kbn-reporting/export_types/png/tsconfig.json b/packages/kbn-reporting/export_types/png/tsconfig.json new file mode 100644 index 0000000000000..bac09188079b5 --- /dev/null +++ b/packages/kbn-reporting/export_types/png/tsconfig.json @@ -0,0 +1,28 @@ +{ + "extends": "../../../../tsconfig.base.json", + "compilerOptions": { + "outDir": "target/types", + "types": [ + "jest", + "node", + "react" + ] + }, + "include": [ + "**/*.ts", + "**/*.tsx", + ], + "exclude": [ + "target/**/*" + ], + "kbn_references": [ + "@kbn/reporting-common", + "@kbn/licensing-plugin", + "@kbn/screenshotting-plugin", + "@kbn/reporting-server", + "@kbn/reporting-export-types-png-common", + "@kbn/core", + "@kbn/reporting-mocks-server", + "@kbn/logging", + ] +} diff --git a/packages/kbn-reporting/export_types/png_common/README.md b/packages/kbn-reporting/export_types/png_common/README.md new file mode 100644 index 0000000000000..c88edfc9cf8f0 --- /dev/null +++ b/packages/kbn-reporting/export_types/png_common/README.md @@ -0,0 +1,3 @@ +# @kbn/reporting-export-types-png-common + +Empty package generated by @kbn/generate diff --git a/packages/kbn-reporting/export_types/png_common/constants.ts b/packages/kbn-reporting/export_types/png_common/constants.ts new file mode 100644 index 0000000000000..b19732cd417ce --- /dev/null +++ b/packages/kbn-reporting/export_types/png_common/constants.ts @@ -0,0 +1,13 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may 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 PNG_REPORT_TYPE = 'PNG'; +export const PNG_REPORT_TYPE_V2 = 'pngV2'; + +export const PNG_JOB_TYPE = 'PNG'; +export const PNG_JOB_TYPE_V2 = 'PNGV2'; diff --git a/x-pack/plugins/reporting/common/types/export_types/png_v2.ts b/packages/kbn-reporting/export_types/png_common/index.ts similarity index 53% rename from x-pack/plugins/reporting/common/types/export_types/png_v2.ts rename to packages/kbn-reporting/export_types/png_common/index.ts index ff3ff5a692edb..4b2b381fbc059 100644 --- a/x-pack/plugins/reporting/common/types/export_types/png_v2.ts +++ b/packages/kbn-reporting/export_types/png_common/index.ts @@ -1,15 +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. + * 2.0 and the Server Side Public License, v 1; you may 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 { LayoutParams } from '@kbn/screenshotting-plugin/common'; -import type { LocatorParams } from '../url'; -import type { BaseParams, BasePayload } from '../base'; +import type { BaseParams, BasePayload, LocatorParams } from '@kbn/reporting-common/types'; +import { LayoutParams } from '@kbn/screenshotting-plugin/common'; + +export * from './constants'; + +interface BaseParamsPNG { + layout: LayoutParams; + forceNow?: string; + relativeUrl: string; +} + +export type JobParamsPNGDeprecated = BaseParamsPNG & BaseParams; + +// Job payload: structure of stored job data provided by create_job +export type TaskPayloadPNG = BaseParamsPNG & BasePayload; -// Job params: structure of incoming user request data export interface JobParamsPNGV2 extends BaseParams { layout: LayoutParams; /** diff --git a/packages/kbn-reporting/export_types/png_common/kibana.jsonc b/packages/kbn-reporting/export_types/png_common/kibana.jsonc new file mode 100644 index 0000000000000..0c0b7259864ce --- /dev/null +++ b/packages/kbn-reporting/export_types/png_common/kibana.jsonc @@ -0,0 +1,5 @@ +{ + "type": "shared-common", + "id": "@kbn/reporting-export-types-png-common", + "owner": "@elastic/appex-sharedux" +} diff --git a/packages/kbn-reporting/export_types/png_common/package.json b/packages/kbn-reporting/export_types/png_common/package.json new file mode 100644 index 0000000000000..4c25b1d74e04b --- /dev/null +++ b/packages/kbn-reporting/export_types/png_common/package.json @@ -0,0 +1,6 @@ +{ + "name": "@kbn/reporting-export-types-png-common", + "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/kbn-reporting/export_types/png_common/tsconfig.json b/packages/kbn-reporting/export_types/png_common/tsconfig.json new file mode 100644 index 0000000000000..cb0a7b461eda8 --- /dev/null +++ b/packages/kbn-reporting/export_types/png_common/tsconfig.json @@ -0,0 +1,20 @@ +{ + "extends": "../../../../tsconfig.base.json", + "compilerOptions": { + "outDir": "target/types", + "types": [ + "jest", + "node" + ] + }, + "include": [ + "**/*.ts", + ], + "exclude": [ + "target/**/*" + ], + "kbn_references": [ + "@kbn/screenshotting-plugin", + "@kbn/reporting-common", + ] +} diff --git a/packages/kbn-reporting/mocks_server/README.md b/packages/kbn-reporting/mocks_server/README.md new file mode 100644 index 0000000000000..b77e23746b551 --- /dev/null +++ b/packages/kbn-reporting/mocks_server/README.md @@ -0,0 +1,3 @@ +# @kbn/reporting-mocks-server + +Empty package generated by @kbn/generate diff --git a/packages/kbn-reporting/mocks_server/index.ts b/packages/kbn-reporting/mocks_server/index.ts new file mode 100644 index 0000000000000..8367754a97f34 --- /dev/null +++ b/packages/kbn-reporting/mocks_server/index.ts @@ -0,0 +1,48 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import type { DeepPartial } from 'utility-types'; +import type { ReportingConfigType } from '@kbn/reporting-server'; + +export const createMockConfigSchema = ( + overrides: DeepPartial = {} +): ReportingConfigType => { + // deeply merge the defaults and the provided partial schema + return { + index: '.reporting', + encryptionKey: 'cool-encryption-key-where-did-you-find-it', + ...overrides, + kibanaServer: { + hostname: 'localhost', + ...overrides.kibanaServer, + }, + queue: { + indexInterval: 'week', + pollEnabled: true, + pollInterval: 3000, + timeout: 120000, + ...overrides.queue, + }, + csv: { + scroll: { size: 500, duration: '30s' }, + ...overrides.csv, + }, + roles: { + enabled: false, + ...overrides.roles, + }, + capture: { maxAttempts: 1 }, + export_types: { + pdf: { enabled: true }, + png: { enabled: true }, + csv: { enabled: true }, + ...overrides.export_types, + }, + statefulSettings: { enabled: true }, + } as ReportingConfigType; +}; diff --git a/packages/kbn-reporting/mocks_server/jest.config.js b/packages/kbn-reporting/mocks_server/jest.config.js new file mode 100644 index 0000000000000..ce39471ef378a --- /dev/null +++ b/packages/kbn-reporting/mocks_server/jest.config.js @@ -0,0 +1,13 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +module.exports = { + preset: '@kbn/test/jest_node', + rootDir: '../../..', + roots: ['/packages/kbn-reporting/mocks_server'], +}; diff --git a/packages/kbn-generate-csv-types/kibana.jsonc b/packages/kbn-reporting/mocks_server/kibana.jsonc similarity index 63% rename from packages/kbn-generate-csv-types/kibana.jsonc rename to packages/kbn-reporting/mocks_server/kibana.jsonc index 349c85eff2558..e9c9707b67a2a 100644 --- a/packages/kbn-generate-csv-types/kibana.jsonc +++ b/packages/kbn-reporting/mocks_server/kibana.jsonc @@ -1,5 +1,5 @@ { "type": "shared-common", - "id": "@kbn/generate-csv-types", + "id": "@kbn/reporting-mocks-server", "owner": "@elastic/appex-sharedux" } diff --git a/packages/kbn-reporting/mocks_server/package.json b/packages/kbn-reporting/mocks_server/package.json new file mode 100644 index 0000000000000..88b3ac4715569 --- /dev/null +++ b/packages/kbn-reporting/mocks_server/package.json @@ -0,0 +1,6 @@ +{ + "name": "@kbn/reporting-mocks-server", + "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/kbn-reporting/mocks_server/tsconfig.json b/packages/kbn-reporting/mocks_server/tsconfig.json new file mode 100644 index 0000000000000..ef36887c668e2 --- /dev/null +++ b/packages/kbn-reporting/mocks_server/tsconfig.json @@ -0,0 +1,19 @@ +{ + "extends": "../../../tsconfig.base.json", + "compilerOptions": { + "outDir": "target/types", + "types": [ + "jest", + "node" + ] + }, + "include": [ + "**/*.ts", + ], + "exclude": [ + "target/**/*" + ], + "kbn_references": [ + "@kbn/reporting-server", + ] +} diff --git a/packages/kbn-reporting/public/README.md b/packages/kbn-reporting/public/README.md new file mode 100644 index 0000000000000..76d4926820b7f --- /dev/null +++ b/packages/kbn-reporting/public/README.md @@ -0,0 +1,3 @@ +# @kbn/reporting-public + +Empty package generated by @kbn/generate diff --git a/packages/kbn-reporting/public/index.ts b/packages/kbn-reporting/public/index.ts new file mode 100644 index 0000000000000..7168d6768c5a2 --- /dev/null +++ b/packages/kbn-reporting/public/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 type { ClientConfigType } from './types'; diff --git a/packages/kbn-reporting/public/jest.config.js b/packages/kbn-reporting/public/jest.config.js new file mode 100644 index 0000000000000..9b1a02aee8ea6 --- /dev/null +++ b/packages/kbn-reporting/public/jest.config.js @@ -0,0 +1,13 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +module.exports = { + preset: '@kbn/test/jest_node', + rootDir: '../../..', + roots: ['/packages/kbn-reporting/public'], +}; diff --git a/packages/kbn-reporting/public/kibana.jsonc b/packages/kbn-reporting/public/kibana.jsonc new file mode 100644 index 0000000000000..c813e18f70e8e --- /dev/null +++ b/packages/kbn-reporting/public/kibana.jsonc @@ -0,0 +1,5 @@ +{ + "type": "shared-browser", + "id": "@kbn/reporting-public", + "owner": "@elastic/appex-sharedux" +} diff --git a/packages/kbn-generate-csv-types/package.json b/packages/kbn-reporting/public/package.json similarity index 71% rename from packages/kbn-generate-csv-types/package.json rename to packages/kbn-reporting/public/package.json index 7c34b87f1524a..b9a4abf894c64 100644 --- a/packages/kbn-generate-csv-types/package.json +++ b/packages/kbn-reporting/public/package.json @@ -1,5 +1,5 @@ { - "name": "@kbn/generate-csv-types", + "name": "@kbn/reporting-public", "private": true, "version": "1.0.0", "license": "SSPL-1.0 OR Elastic License 2.0" diff --git a/packages/kbn-reporting/public/tsconfig.json b/packages/kbn-reporting/public/tsconfig.json new file mode 100644 index 0000000000000..6d27b06d5f8ba --- /dev/null +++ b/packages/kbn-reporting/public/tsconfig.json @@ -0,0 +1,17 @@ +{ + "extends": "../../../tsconfig.base.json", + "compilerOptions": { + "outDir": "target/types", + "types": [ + "jest", + "node" + ] + }, + "include": [ + "**/*.ts", + ], + "exclude": [ + "target/**/*" + ], + "kbn_references": [] +} diff --git a/packages/kbn-reporting/public/types.ts b/packages/kbn-reporting/public/types.ts new file mode 100644 index 0000000000000..34aa52544ca76 --- /dev/null +++ b/packages/kbn-reporting/public/types.ts @@ -0,0 +1,14 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +export interface ClientConfigType { + poll: { jobsRefresh: { interval: number; intervalErrorMultiplier: number } }; + roles: { enabled: boolean }; + export_types: { pdf: { enabled: boolean }; png: { enabled: boolean }; csv: { enabled: boolean } }; + statefulSettings: { enabled: boolean }; +} diff --git a/x-pack/plugins/reporting/server/config/__snapshots__/schema.test.ts.snap b/packages/kbn-reporting/server/__snapshots__/config_schema.test.ts.snap similarity index 100% rename from x-pack/plugins/reporting/server/config/__snapshots__/schema.test.ts.snap rename to packages/kbn-reporting/server/__snapshots__/config_schema.test.ts.snap diff --git a/x-pack/plugins/reporting/server/config/schema.test.ts b/packages/kbn-reporting/server/config_schema.test.ts similarity index 94% rename from x-pack/plugins/reporting/server/config/schema.test.ts rename to packages/kbn-reporting/server/config_schema.test.ts index f30be71db09ea..069218e988019 100644 --- a/x-pack/plugins/reporting/server/config/schema.test.ts +++ b/packages/kbn-reporting/server/config_schema.test.ts @@ -1,11 +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. + * 2.0 and the Server Side Public License, v 1; you may 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 { ConfigSchema } from './schema'; +import { ConfigSchema } from './config_schema'; describe('Reporting Config Schema', () => { it(`context {"dev":false,"dist":false} produces correct config`, () => { diff --git a/x-pack/plugins/reporting/server/config/schema.ts b/packages/kbn-reporting/server/config_schema.ts similarity index 94% rename from x-pack/plugins/reporting/server/config/schema.ts rename to packages/kbn-reporting/server/config_schema.ts index ff0cda89a693b..3aab7be6e660c 100644 --- a/x-pack/plugins/reporting/server/config/schema.ts +++ b/packages/kbn-reporting/server/config_schema.ts @@ -1,11 +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. + * 2.0 and the Server Side Public License, v 1; you may 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 { ByteSizeValue, offeringBasedSchema, schema, TypeOf } from '@kbn/config-schema'; +import { ByteSizeValue, offeringBasedSchema, schema } from '@kbn/config-schema'; import ipaddr from 'ipaddr.js'; import { sum } from 'lodash'; import moment from 'moment'; @@ -147,5 +148,3 @@ export const ConfigSchema = schema.object({ export_types: ExportTypeSchema, statefulSettings: SettingsSchema, }); - -export type ReportingConfigType = TypeOf; diff --git a/x-pack/plugins/reporting/server/lib/crypto.ts b/packages/kbn-reporting/server/crypto.ts similarity index 68% rename from x-pack/plugins/reporting/server/lib/crypto.ts rename to packages/kbn-reporting/server/crypto.ts index 40a2298eb0fdc..fd812f9868596 100644 --- a/x-pack/plugins/reporting/server/lib/crypto.ts +++ b/packages/kbn-reporting/server/crypto.ts @@ -1,8 +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. + * 2.0 and the Server Side Public License, v 1; you may 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 nodeCrypto from '@elastic/node-crypto'; diff --git a/x-pack/plugins/reporting/server/export_types/common/decrypt_job_headers.test.ts b/packages/kbn-reporting/server/decrypt_job_headers.test.ts similarity index 84% rename from x-pack/plugins/reporting/server/export_types/common/decrypt_job_headers.test.ts rename to packages/kbn-reporting/server/decrypt_job_headers.test.ts index a65be580adca3..b4515e29d1efa 100644 --- a/x-pack/plugins/reporting/server/export_types/common/decrypt_job_headers.test.ts +++ b/packages/kbn-reporting/server/decrypt_job_headers.test.ts @@ -1,13 +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. + * 2.0 and the Server Side Public License, v 1; you may 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 { loggingSystemMock } from '@kbn/core/server/mocks'; -import { cryptoFactory } from '../../lib'; -import { decryptJobHeaders } from '.'; +import { cryptoFactory, decryptJobHeaders } from '.'; const logger = loggingSystemMock.createLogger(); diff --git a/x-pack/plugins/reporting/server/export_types/common/decrypt_job_headers.ts b/packages/kbn-reporting/server/decrypt_job_headers.ts similarity index 76% rename from x-pack/plugins/reporting/server/export_types/common/decrypt_job_headers.ts rename to packages/kbn-reporting/server/decrypt_job_headers.ts index 13b8b4804e6fb..35c31e2a10dad 100644 --- a/x-pack/plugins/reporting/server/export_types/common/decrypt_job_headers.ts +++ b/packages/kbn-reporting/server/decrypt_job_headers.ts @@ -1,13 +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. + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. */ import { i18n } from '@kbn/i18n'; import type { Logger } from '@kbn/core/server'; -import { cryptoFactory } from '../../lib'; +import { cryptoFactory } from './crypto'; export const decryptJobHeaders = async ( encryptionKey: string | undefined, @@ -17,7 +18,7 @@ export const decryptJobHeaders = async ( try { if (typeof headers !== 'string') { throw new Error( - i18n.translate('xpack.reporting.exportTypes.common.missingJobHeadersErrorMessage', { + i18n.translate('reporting.commonExportTypesHelpers.missingJobHeadersErrorMessage', { defaultMessage: 'Job headers are missing', }) ); @@ -30,7 +31,7 @@ export const decryptJobHeaders = async ( throw new Error( i18n.translate( - 'xpack.reporting.exportTypes.common.failedToDecryptReportJobDataErrorMessage', + 'reporting.commonExportTypesHelpers.failedToDecryptReportJobDataErrorMessage', { defaultMessage: 'Failed to decrypt report job data. Please ensure that {encryptionKey} is set and re-generate this report. {err}', diff --git a/x-pack/plugins/reporting/server/export_types/common/export_type.ts b/packages/kbn-reporting/server/export_type.ts similarity index 68% rename from x-pack/plugins/reporting/server/export_types/common/export_type.ts rename to packages/kbn-reporting/server/export_type.ts index 96240863122d0..7765fe6dd7e26 100644 --- a/x-pack/plugins/reporting/server/export_types/common/export_type.ts +++ b/packages/kbn-reporting/server/export_type.ts @@ -1,32 +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. + * 2.0 and the Server Side Public License, v 1; you may 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 { - IBasePath, - Headers, - Logger, - CoreKibanaRequest, - CoreSetup, +import type { IClusterClient } from '@kbn/core-elasticsearch-server'; +import { CoreKibanaRequest } from '@kbn/core-http-router-server-internal'; +import type { FakeRawRequest, + Headers, HttpServiceSetup, + IBasePath, KibanaRequest, - PluginInitializerContext, - SavedObjectsClientContract, - SavedObjectsServiceStart, - UiSettingsServiceStart, - IClusterClient, -} from '@kbn/core/server'; -import { LicenseType } from '@kbn/licensing-plugin/common/types'; -import { ScreenshottingStart } from '@kbn/screenshotting-plugin/server'; +} from '@kbn/core-http-server'; +import type { CoreSetup } from '@kbn/core-lifecycle-server'; +import type { PluginInitializerContext } from '@kbn/core-plugins-server'; +import type { SavedObjectsClientContract } from '@kbn/core-saved-objects-api-server'; +import type { SavedObjectsServiceStart } from '@kbn/core-saved-objects-server'; +import type { UiSettingsServiceStart } from '@kbn/core-ui-settings-server'; +import type { LicenseType } from '@kbn/licensing-plugin/common/types'; +import type { Logger } from '@kbn/logging'; +import type { ReportingServerInfo } from '@kbn/reporting-common/types'; +import type { ScreenshottingStart } from '@kbn/screenshotting-plugin/server'; import { DEFAULT_SPACE_ID } from '@kbn/spaces-plugin/common'; -import { SpacesPluginSetup } from '@kbn/spaces-plugin/server'; -import { ReportingConfigType } from '../../config'; -import { ReportingServerInfo } from '../../core'; -import { CreateJobFn, ReportingStart, RunTaskFn } from '../../types'; +import type { SpacesPluginSetup } from '@kbn/spaces-plugin/server'; + +import type { CreateJobFn, RunTaskFn } from './types'; +import type { ReportingConfigType } from '.'; export interface BaseExportTypeSetupDeps { basePath: Pick; @@ -38,7 +40,6 @@ export interface BaseExportTypeStartDeps { uiSettings: UiSettingsServiceStart; esClient: IClusterClient; screenshotting?: ScreenshottingStart; - reporting: ReportingStart; } export abstract class ExportType< @@ -84,6 +85,20 @@ export abstract class ExportType< return savedObjects.getScopedClient(request) as SavedObjectsClientContract; } + private getSpaceId(request: KibanaRequest, logger = this.logger): string | undefined { + const spacesService = this.setupDeps.spaces?.spacesService; + if (spacesService) { + const spaceId = spacesService?.getSpaceId(request); + + if (spaceId !== DEFAULT_SPACE_ID) { + logger.info(`Request uses Space ID: ${spaceId}`); + return spaceId; + } else { + logger.debug(`Request uses default Space`); + } + } + } + // needed to be protected vs private for the csv search source immediate export type protected getUiSettingsServiceFactory(savedObjectsClient: SavedObjectsClientContract) { const { uiSettings: uiSettingsService } = this.startDeps; @@ -93,7 +108,7 @@ export abstract class ExportType< protected async getUiSettingsClient(request: KibanaRequest, logger = this.logger) { const spacesService = this.setupDeps.spaces?.spacesService; - const spaceId = this.startDeps.reporting.getSpaceId(request, logger); + const spaceId = this.getSpaceId(request, logger); if (spacesService && spaceId) { logger.info(`Creating UI Settings Client for space: ${spaceId}`); diff --git a/x-pack/plugins/reporting/server/export_types/common/v2/get_full_redirect_app_url.test.ts b/packages/kbn-reporting/server/get_full_redirect_app_url.test.ts similarity index 80% rename from x-pack/plugins/reporting/server/export_types/common/v2/get_full_redirect_app_url.test.ts rename to packages/kbn-reporting/server/get_full_redirect_app_url.test.ts index a37da0f0eb45d..637bed536859c 100644 --- a/x-pack/plugins/reporting/server/export_types/common/v2/get_full_redirect_app_url.test.ts +++ b/packages/kbn-reporting/server/get_full_redirect_app_url.test.ts @@ -1,11 +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. + * 2.0 and the Server Side Public License, v 1; you may 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 { ReportingConfigType } from '../../../config'; +import type { ReportingConfigType } from '.'; import { getFullRedirectAppUrl } from './get_full_redirect_app_url'; describe('getFullRedirectAppUrl', () => { diff --git a/x-pack/plugins/reporting/server/export_types/common/v2/get_full_redirect_app_url.ts b/packages/kbn-reporting/server/get_full_redirect_app_url.ts similarity index 66% rename from x-pack/plugins/reporting/server/export_types/common/v2/get_full_redirect_app_url.ts rename to packages/kbn-reporting/server/get_full_redirect_app_url.ts index 9191e886b8f68..e09f7b8ceed9d 100644 --- a/x-pack/plugins/reporting/server/export_types/common/v2/get_full_redirect_app_url.ts +++ b/packages/kbn-reporting/server/get_full_redirect_app_url.ts @@ -1,15 +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. + * 2.0 and the Server Side Public License, v 1; you may 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 { format } from 'url'; -import { ReportingServerInfo } from '../../../core'; -import { ReportingConfigType } from '../../../config'; -import { buildKibanaPath } from '../../../../common/build_kibana_path'; -import { getRedirectAppPath } from '../../../../common/constants'; + +import { buildKibanaPath, getRedirectAppPath } from '@kbn/reporting-common'; +import type { ReportingServerInfo } from '@kbn/reporting-common/types'; +import type { ReportingConfigType } from '.'; export function getFullRedirectAppUrl( config: ReportingConfigType, diff --git a/packages/kbn-reporting/server/index.ts b/packages/kbn-reporting/server/index.ts new file mode 100644 index 0000000000000..08240bc28fe0a --- /dev/null +++ b/packages/kbn-reporting/server/index.ts @@ -0,0 +1,18 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may 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 { cryptoFactory } from './crypto'; +export { decryptJobHeaders } from './decrypt_job_headers'; +export { ExportType } from './export_type'; +export { getFullRedirectAppUrl } from './get_full_redirect_app_url'; +export { getFieldFormats, setFieldFormats } from './services'; + +export type { BaseExportTypeSetupDeps, BaseExportTypeStartDeps } from './export_type'; +export { ConfigSchema } from './config_schema'; + +export * from './types'; diff --git a/packages/kbn-reporting/server/jest.config.js b/packages/kbn-reporting/server/jest.config.js new file mode 100644 index 0000000000000..9b805e9133994 --- /dev/null +++ b/packages/kbn-reporting/server/jest.config.js @@ -0,0 +1,13 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +module.exports = { + preset: '@kbn/test', + rootDir: '../../..', + roots: ['/packages/kbn-reporting/server'], +}; diff --git a/packages/kbn-reporting/server/kibana.jsonc b/packages/kbn-reporting/server/kibana.jsonc new file mode 100644 index 0000000000000..a2440596bd9dd --- /dev/null +++ b/packages/kbn-reporting/server/kibana.jsonc @@ -0,0 +1,10 @@ +{ + "type": "shared-server", + "id": "@kbn/reporting-server", + "owner": "@elastic/appex-sharedux", + "plugin": { + "server": true, + "browser": false, + } + } + diff --git a/packages/kbn-reporting/server/package.json b/packages/kbn-reporting/server/package.json new file mode 100644 index 0000000000000..0db86c14c1390 --- /dev/null +++ b/packages/kbn-reporting/server/package.json @@ -0,0 +1,6 @@ +{ + "name": "@kbn/reporting-server", + "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/kbn-reporting/server/services.ts b/packages/kbn-reporting/server/services.ts new file mode 100644 index 0000000000000..ea1f47c01b4ed --- /dev/null +++ b/packages/kbn-reporting/server/services.ts @@ -0,0 +1,13 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import type { FieldFormatsStart } from '@kbn/field-formats-plugin/server'; +import { createGetterSetter } from '@kbn/kibana-utils-plugin/common'; + +export const [getFieldFormats, setFieldFormats] = + createGetterSetter('FieldFormats'); diff --git a/packages/kbn-reporting/server/tsconfig.json b/packages/kbn-reporting/server/tsconfig.json new file mode 100644 index 0000000000000..7981ce1c3f995 --- /dev/null +++ b/packages/kbn-reporting/server/tsconfig.json @@ -0,0 +1,38 @@ +{ + "extends": "../../../tsconfig.base.json", + "compilerOptions": { + "outDir": "target/types", + "types": [ + "jest", + "node", + ] + }, + "include": [ + "**/*.ts", + "**/*.tsx", + ], + "exclude": [ + "target/**/*" + ], + "kbn_references": [ + "@kbn/i18n", + "@kbn/screenshotting-plugin", + "@kbn/field-formats-plugin", + "@kbn/kibana-utils-plugin", + "@kbn/logging", + "@kbn/core", + "@kbn/reporting-common", + "@kbn/core-http-server", + "@kbn/core-lifecycle-server", + "@kbn/core-plugins-server", + "@kbn/core-saved-objects-api-server", + "@kbn/core-saved-objects-server", + "@kbn/core-ui-settings-server", + "@kbn/licensing-plugin", + "@kbn/spaces-plugin", + "@kbn/core-elasticsearch-server", + "@kbn/core-http-router-server-internal", + "@kbn/core-http-request-handler-context-server", + "@kbn/config-schema", + ] +} diff --git a/packages/kbn-reporting/server/types.ts b/packages/kbn-reporting/server/types.ts new file mode 100644 index 0000000000000..94ad1e34a19d3 --- /dev/null +++ b/packages/kbn-reporting/server/types.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 { Writable } from 'stream'; + +import type { TypeOf } from '@kbn/config-schema'; +import type { CustomRequestHandlerContext } from '@kbn/core-http-request-handler-context-server'; +import type { KibanaRequest } from '@kbn/core-http-server'; +import type { CancellationToken } from '@kbn/reporting-common'; +import type { BaseParams, BasePayload, TaskRunResult } from '@kbn/reporting-common/types'; + +import { ConfigSchema } from './config_schema'; +import type { ExportType } from './export_type'; + +export interface ReportingServerPluginSetup { + registerExportTypes: (item: ExportType) => void; + /** + * Used to inform plugins if Reporting config is compatible with UI Capabilities / Application Sub-Feature Controls + */ + usesUiCapabilities: () => boolean; +} + +// standard type for create job function of any ExportType implementation +export type CreateJobFn = ( + jobParams: JobParamsType, + context: CustomRequestHandlerContext<{ + reporting: ReportingServerPluginSetup | null; + }>, + req: KibanaRequest +) => Promise>; + +// standard type for run task function of any ExportType implementation +export type RunTaskFn = ( + jobId: string, + payload: TaskPayloadType, + cancellationToken: CancellationToken, + stream: Writable +) => Promise; + +export interface TimeRangeParams { + min?: Date | string | number | null; + max?: Date | string | number | null; +} + +export type ReportingConfigType = TypeOf; diff --git a/packages/kbn-search-connectors/components/sync_jobs/__snapshots__/pipeline_panel.test.tsx.snap b/packages/kbn-search-connectors/components/sync_jobs/__snapshots__/pipeline_panel.test.tsx.snap index 6781298c2aaa6..cddd85fc851b9 100644 --- a/packages/kbn-search-connectors/components/sync_jobs/__snapshots__/pipeline_panel.test.tsx.snap +++ b/packages/kbn-search-connectors/components/sync_jobs/__snapshots__/pipeline_panel.test.tsx.snap @@ -33,7 +33,7 @@ exports[`PipelinePanel renders 1`] = ` }, Object { "setting": "Machine learning inference", - "value": false, + "value": true, }, ] } diff --git a/packages/kbn-search-connectors/components/sync_jobs/pipeline_panel.test.tsx b/packages/kbn-search-connectors/components/sync_jobs/pipeline_panel.test.tsx index b65769f3372a7..8d8145d1c5ecd 100644 --- a/packages/kbn-search-connectors/components/sync_jobs/pipeline_panel.test.tsx +++ b/packages/kbn-search-connectors/components/sync_jobs/pipeline_panel.test.tsx @@ -17,7 +17,7 @@ describe('PipelinePanel', () => { extract_binary_content: true, name: 'name', reduce_whitespace: true, - run_ml_inference: false, + run_ml_inference: true, }; it('renders', () => { const wrapper = shallow(); diff --git a/packages/kbn-search-response-warnings/index.ts b/packages/kbn-search-response-warnings/index.ts index 88b61320b99f7..6c3a1ad5487ad 100644 --- a/packages/kbn-search-response-warnings/index.ts +++ b/packages/kbn-search-response-warnings/index.ts @@ -9,11 +9,15 @@ export type { SearchResponseWarning, WarningHandlerCallback } from './src/types'; export { + getWarningsDescription, + getWarningsTitle, SearchResponseWarningsBadge, SearchResponseWarningsBadgePopoverContent, SearchResponseWarningsCallout, SearchResponseWarningsEmptyPrompt, + ViewDetailsPopover, } from './src/components/search_response_warnings'; +export { extractWarnings } from './src/extract_warnings'; export { handleWarnings } from './src/handle_warnings'; export { hasUnsupportedDownsampledAggregationFailure } from './src/has_unsupported_downsampled_aggregation_failure'; diff --git a/packages/kbn-search-response-warnings/src/components/search_response_warnings/index.ts b/packages/kbn-search-response-warnings/src/components/search_response_warnings/index.ts index 06c2b2c18e31a..ff27f996be2a7 100644 --- a/packages/kbn-search-response-warnings/src/components/search_response_warnings/index.ts +++ b/packages/kbn-search-response-warnings/src/components/search_response_warnings/index.ts @@ -6,7 +6,9 @@ * Side Public License, v 1. */ +export { getWarningsDescription, getWarningsTitle } from './i18n_utils'; export { SearchResponseWarningsBadge } from './badge'; export { SearchResponseWarningsBadgePopoverContent } from './badge_popover_content'; export { SearchResponseWarningsCallout } from './callout'; export { SearchResponseWarningsEmptyPrompt } from './empty_prompt'; +export { ViewDetailsPopover } from './view_details_popover'; diff --git a/packages/kbn-test/src/kbn_client/kbn_client_ui_settings.ts b/packages/kbn-test/src/kbn_client/kbn_client_ui_settings.ts index 8b9277fdab8b9..599184b30a461 100644 --- a/packages/kbn-test/src/kbn_client/kbn_client_ui_settings.ts +++ b/packages/kbn-test/src/kbn_client/kbn_client_ui_settings.ts @@ -10,7 +10,7 @@ import { ToolingLog } from '@kbn/tooling-log'; import { KbnClientRequester, pathWithSpace } from './kbn_client_requester'; -export type UiSettingValues = Record; +export type UiSettingValues = Record; interface UiSettingsApiResponse { settings: { [key: string]: { diff --git a/packages/kbn-text-based-editor/src/esql_documentation_sections.tsx b/packages/kbn-text-based-editor/src/esql_documentation_sections.tsx index 6f244647922ef..4114ab021bf71 100644 --- a/packages/kbn-text-based-editor/src/esql_documentation_sections.tsx +++ b/packages/kbn-text-based-editor/src/esql_documentation_sections.tsx @@ -1180,7 +1180,7 @@ Rounds down a date to the closest interval. \`\`\` FROM employees -| EVAL year_hired = DATE_TRUNC(hire_date, 1 year) +| EVAL year_hired = DATE_TRUNC(1 year, hire_date) | STATS count(emp_no) BY year_hired | SORT year_hired \`\`\` diff --git a/packages/kbn-unified-field-list/src/components/field_popover/field_popover.scss b/packages/kbn-unified-field-list/src/components/field_popover/field_popover.scss index 8e5a7d5963a8b..b8fe997d01c13 100644 --- a/packages/kbn-unified-field-list/src/components/field_popover/field_popover.scss +++ b/packages/kbn-unified-field-list/src/components/field_popover/field_popover.scss @@ -3,5 +3,5 @@ .unifiedFieldList__fieldPopover__fieldPopoverPanel { min-width: $euiSizeXXL * 6.5 !important; /* 1 */ - max-width: $euiSizeXXL * 7.5 !important; + max-width: $euiSizeXXL * 10 !important; } diff --git a/packages/kbn-unified-field-list/src/components/field_stats/field_top_values_bucket.tsx b/packages/kbn-unified-field-list/src/components/field_stats/field_top_values_bucket.tsx index ccae2a3dfffc1..f296fe74906eb 100755 --- a/packages/kbn-unified-field-list/src/components/field_stats/field_top_values_bucket.tsx +++ b/packages/kbn-unified-field-list/src/components/field_stats/field_top_values_bucket.tsx @@ -13,6 +13,7 @@ import { EuiFlexItem, EuiProgress, EuiText, + EuiTextBlockTruncate, EuiToolTip, } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; @@ -84,14 +85,18 @@ const FieldTopValuesBucket: React.FC = ({ {(formattedFieldValue?.length ?? 0) > 0 ? ( - - {formattedFieldValue} - + + + {formattedFieldValue} + + ) : ( diff --git a/packages/kbn-visualization-ui-components/components/field_picker/field_picker.tsx b/packages/kbn-visualization-ui-components/components/field_picker/field_picker.tsx index 4827bb2fd628c..5b6022d5cb454 100644 --- a/packages/kbn-visualization-ui-components/components/field_picker/field_picker.tsx +++ b/packages/kbn-visualization-ui-components/components/field_picker/field_picker.tsx @@ -7,14 +7,11 @@ */ import './field_picker.scss'; -import React, { useRef } from 'react'; +import React from 'react'; import { i18n } from '@kbn/i18n'; -import useEffectOnce from 'react-use/lib/useEffectOnce'; -import { EuiComboBox, EuiComboBoxProps, EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; +import { EuiComboBox, EuiComboBoxProps } from '@elastic/eui'; import { FieldIcon } from '@kbn/field-utils/src/components/field_icon'; import classNames from 'classnames'; -import type { DataType } from './types'; -import { TruncatedLabel } from './truncated_label'; import type { FieldOptionValue, FieldOption } from './types'; export interface FieldPickerProps @@ -27,9 +24,8 @@ export interface FieldPickerProps 'data-test-subj'?: string; } -const DEFAULT_COMBOBOX_WIDTH = 305; -const COMBOBOX_PADDINGS = 90; -const DEFAULT_FONT = '14px Inter'; +const MIDDLE_TRUNCATION_PROPS = { truncation: 'middle' as const }; +const SINGLE_SELECTION_AS_TEXT_PROPS = { asPlainText: true }; export function FieldPicker({ selectedOptions, @@ -40,95 +36,86 @@ export function FieldPicker({ ['data-test-subj']: dataTestSub, ...rest }: FieldPickerProps) { + let theLongestLabel = ''; const styledOptions = options?.map(({ compatible, exists, ...otherAttr }) => { if (otherAttr.options) { return { ...otherAttr, - options: otherAttr.options.map(({ exists: fieldOptionExists, ...fieldOption }) => ({ - ...fieldOption, - className: classNames({ - 'lnFieldPicker__option--incompatible': !fieldOption.compatible, - 'lnFieldPicker__option--nonExistant': !fieldOptionExists, - }), - })), + options: otherAttr.options.map(({ exists: fieldOptionExists, ...fieldOption }) => { + if (fieldOption.label.length > theLongestLabel.length) { + theLongestLabel = fieldOption.label; + } + return { + ...fieldOption, + prepend: fieldOption.value.dataType ? ( + + ) : null, + className: classNames({ + 'lnFieldPicker__option--incompatible': !fieldOption.compatible, + 'lnFieldPicker__option--nonExistant': !fieldOptionExists, + }), + }; + }), }; } return { ...otherAttr, compatible, + prepend: otherAttr.value.dataType ? ( + + ) : null, className: classNames({ 'lnFieldPicker__option--incompatible': !compatible, 'lnFieldPicker__option--nonExistant': !exists, }), }; }); - const comboBoxRef = useRef(null); - const [labelProps, setLabelProps] = React.useState<{ - width: number; - font: string; - }>({ - width: DEFAULT_COMBOBOX_WIDTH - COMBOBOX_PADDINGS, - font: DEFAULT_FONT, - }); - - const computeStyles = (_e: UIEvent | undefined, shouldRecomputeAll = false) => { - if (comboBoxRef.current) { - const current = { - ...labelProps, - width: comboBoxRef.current?.clientWidth - COMBOBOX_PADDINGS, - }; - if (shouldRecomputeAll) { - current.font = window.getComputedStyle(comboBoxRef.current).font; - } - setLabelProps(current); - } - }; - - useEffectOnce(() => { - if (comboBoxRef.current) { - computeStyles(undefined, true); - } - window.addEventListener('resize', computeStyles); - }); + const panelMinWidth = getPanelMinWidth(theLongestLabel.length); return ( -
- { - if (choices.length === 0) { - onDelete?.(); - return; - } - onChoose(choices[0].value); - }} - renderOption={(option, searchValue) => { - return ( - - - - - - - - - ); - }} - {...rest} - /> -
+ { + if (choices.length === 0) { + onDelete?.(); + return; + } + onChoose(choices[0].value); + }} + {...rest} + /> ); } + +const MINIMUM_POPOVER_WIDTH = 300; +const MINIMUM_POPOVER_WIDTH_CHAR_COUNT = 28; +const AVERAGE_CHAR_WIDTH = 7; +const MAXIMUM_POPOVER_WIDTH_CHAR_COUNT = 60; +const MAXIMUM_POPOVER_WIDTH = 550; // fitting 60 characters + +function getPanelMinWidth(labelLength: number) { + if (labelLength > MAXIMUM_POPOVER_WIDTH_CHAR_COUNT) { + return MAXIMUM_POPOVER_WIDTH; + } + if (labelLength > MINIMUM_POPOVER_WIDTH_CHAR_COUNT) { + const overflownChars = labelLength - MINIMUM_POPOVER_WIDTH_CHAR_COUNT; + return MINIMUM_POPOVER_WIDTH + overflownChars * AVERAGE_CHAR_WIDTH; + } + return MINIMUM_POPOVER_WIDTH; +} diff --git a/packages/kbn-visualization-ui-components/components/field_picker/index.ts b/packages/kbn-visualization-ui-components/components/field_picker/index.ts index 96f53e2bfc74a..e21e97911ecbd 100644 --- a/packages/kbn-visualization-ui-components/components/field_picker/index.ts +++ b/packages/kbn-visualization-ui-components/components/field_picker/index.ts @@ -7,5 +7,4 @@ */ export { FieldPicker } from './field_picker'; -export { TruncatedLabel } from './truncated_label'; export type { FieldOptionValue, FieldOption, DataType } from './types'; diff --git a/packages/kbn-visualization-ui-components/components/field_picker/truncated_label.test.tsx b/packages/kbn-visualization-ui-components/components/field_picker/truncated_label.test.tsx deleted file mode 100644 index fb9b7581bbdc6..0000000000000 --- a/packages/kbn-visualization-ui-components/components/field_picker/truncated_label.test.tsx +++ /dev/null @@ -1,78 +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 { mount } from 'enzyme'; -import { TruncatedLabel } from './truncated_label'; - -describe('truncated_label', () => { - const defaultProps = { - font: '14px Inter', - // jest-canvas-mock mocks measureText as the number of string characters, thats why the width is so low - width: 30, - search: '', - label: 'example_field', - }; - it('displays passed label if shorter than passed labelLength', () => { - const wrapper = mount(); - expect(wrapper.text()).toEqual('example_field'); - }); - it('middle truncates label', () => { - const wrapper = mount( - - ); - expect(wrapper.text()).toEqual('example_….subcategory.subfield'); - }); - describe('with search value passed', () => { - it('constructs truncated label when searching for the string of index = 0', () => { - const wrapper = mount( - - ); - expect(wrapper.text()).toEqual('example_space.example_field.s…'); - expect(wrapper.find('mark').text()).toEqual('example_space'); - }); - it('constructs truncated label when searching for the string in the middle', () => { - const wrapper = mount( - - ); - expect(wrapper.text()).toEqual('…ample_field.subcategory.subf…'); - expect(wrapper.find('mark').text()).toEqual('ample_field'); - }); - it('constructs truncated label when searching for the string at the end of the label', () => { - const wrapper = mount( - - ); - expect(wrapper.text()).toEqual('…le_field.subcategory.subfield'); - expect(wrapper.find('mark').text()).toEqual('subf'); - }); - - it('constructs truncated label when searching for the string longer than the truncated width and highlights the whole content', () => { - const wrapper = mount( - - ); - expect(wrapper.text()).toEqual('…ample_space.example_field.su…'); - expect(wrapper.find('mark').text()).toEqual('…ample_space.example_field.su…'); - }); - }); -}); diff --git a/packages/kbn-visualization-ui-components/components/field_picker/truncated_label.tsx b/packages/kbn-visualization-ui-components/components/field_picker/truncated_label.tsx deleted file mode 100644 index 4715e25acaf05..0000000000000 --- a/packages/kbn-visualization-ui-components/components/field_picker/truncated_label.tsx +++ /dev/null @@ -1,86 +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, { useMemo } from 'react'; -import { EuiMark, EuiHighlight } from '@elastic/eui'; - -const createContext = () => - document.createElement('canvas').getContext('2d') as CanvasRenderingContext2D; - -// extracted from getTextWidth for performance -const context = createContext(); - -const getTextWidth = (text: string, font: string) => { - const ctx = context ?? createContext(); - ctx.font = font; - const metrics = ctx.measureText(text); - return metrics.width; -}; - -const truncateLabel = ( - width: number, - font: string, - label: string, - approximateLength: number, - labelFn: (label: string, length: number) => string -) => { - let output = labelFn(label, approximateLength); - while (getTextWidth(output, font) > width) { - approximateLength = approximateLength - 1; - output = labelFn(label, approximateLength); - } - return output; -}; - -export const TruncatedLabel = React.memo(function TruncatedLabel({ - label, - width, - search, - font, -}: { - label: string; - search: string; - width: number; - font: string; -}) { - const textWidth = useMemo(() => getTextWidth(label, font), [label, font]); - - if (textWidth < width) { - return {label}; - } - - const searchPosition = label.indexOf(search); - const approximateLen = Math.round((width * label.length) / textWidth); - const separator = `…`; - let separatorsLength = separator.length; - let labelFn; - - if (!search || searchPosition === -1) { - labelFn = (text: string, length: number) => - `${text.substr(0, 8)}${separator}${text.substr(text.length - (length - 8))}`; - } else if (searchPosition === 0) { - // search phrase at the beginning - labelFn = (text: string, length: number) => `${text.substr(0, length)}${separator}`; - } else if (approximateLen > label.length - searchPosition) { - // search phrase close to the end or at the end - labelFn = (text: string, length: number) => `${separator}${text.substr(text.length - length)}`; - } else { - // search phrase is in the middle - labelFn = (text: string, length: number) => - `${separator}${text.substr(searchPosition, length)}${separator}`; - separatorsLength = 2 * separator.length; - } - - const outputLabel = truncateLabel(width, font, label, approximateLen, labelFn); - - return search.length < outputLabel.length - separatorsLength ? ( - {outputLabel} - ) : ( - {outputLabel} - ); -}); diff --git a/packages/kbn-visualization-ui-components/index.ts b/packages/kbn-visualization-ui-components/index.ts index 8b9f29fec31a1..16c51f96a869b 100644 --- a/packages/kbn-visualization-ui-components/index.ts +++ b/packages/kbn-visualization-ui-components/index.ts @@ -8,7 +8,6 @@ export { FieldPicker, - TruncatedLabel, NameInput, DebouncedInput, useDebouncedValue, diff --git a/packages/shared-ux/button_toolbar/src/buttons/add_from_library/add_from_library.tsx b/packages/shared-ux/button_toolbar/src/buttons/add_from_library/add_from_library.tsx index da1d3b8fc8711..b021acd6d5d2a 100644 --- a/packages/shared-ux/button_toolbar/src/buttons/add_from_library/add_from_library.tsx +++ b/packages/shared-ux/button_toolbar/src/buttons/add_from_library/add_from_library.tsx @@ -10,7 +10,7 @@ import { i18n } from '@kbn/i18n'; import React from 'react'; import { ToolbarButton, ToolbarButtonProps } from '../toolbar_button'; -export type Props = Omit; +export type Props = Omit, 'iconType' | 'label' | 'type'>; const label = { getLibraryButtonLabel: () => diff --git a/packages/shared-ux/button_toolbar/src/buttons/toolbar_button/__snapshots__/toolbar_button.test.tsx.snap b/packages/shared-ux/button_toolbar/src/buttons/toolbar_button/__snapshots__/toolbar_button.test.tsx.snap index 05065612bb411..68576d81711a8 100644 --- a/packages/shared-ux/button_toolbar/src/buttons/toolbar_button/__snapshots__/toolbar_button.test.tsx.snap +++ b/packages/shared-ux/button_toolbar/src/buttons/toolbar_button/__snapshots__/toolbar_button.test.tsx.snap @@ -1,6 +1,22 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[` is rendered - default 1`] = ` +exports[` iconButton is rendered - default 1`] = ` + +`; + +exports[` standard is rendered - default 1`] = ` `; -exports[` is rendered - primary 1`] = ` +exports[` standard is rendered - primary 1`] = ` +`; + +exports[` standard is rendered - text wth icon 1`] = ` + `; diff --git a/packages/shared-ux/button_toolbar/src/buttons/toolbar_button/toolbar_button.stories.tsx b/packages/shared-ux/button_toolbar/src/buttons/toolbar_button/toolbar_button.stories.tsx index 580d894ecd042..909ae1cd2845e 100644 --- a/packages/shared-ux/button_toolbar/src/buttons/toolbar_button/toolbar_button.stories.tsx +++ b/packages/shared-ux/button_toolbar/src/buttons/toolbar_button/toolbar_button.stories.tsx @@ -21,6 +21,13 @@ export default { }; const argTypes = { + buttonStyle: { + defaultValue: 'standard', + control: { + type: 'radio', + options: ['standard', 'iconButton'], + }, + }, buttonType: { defaultValue: 'empty', control: { @@ -39,9 +46,15 @@ const argTypes = { type Params = Record; -export const ToolbarButton = ({ buttonType, iconSide }: Params) => { +export const ToolbarButton = ({ buttonStyle, buttonType, iconSide }: Params) => { return ( - + ); }; diff --git a/packages/shared-ux/button_toolbar/src/buttons/toolbar_button/toolbar_button.styles.ts b/packages/shared-ux/button_toolbar/src/buttons/toolbar_button/toolbar_button.styles.ts index 162e81bb4efcb..510bedf9fafbb 100644 --- a/packages/shared-ux/button_toolbar/src/buttons/toolbar_button/toolbar_button.styles.ts +++ b/packages/shared-ux/button_toolbar/src/buttons/toolbar_button/toolbar_button.styles.ts @@ -8,12 +8,39 @@ import { UseEuiTheme } from '@elastic/eui'; +export const fontWeightDefinitions = (euiTheme: UseEuiTheme['euiTheme']) => ({ + bold: euiTheme.font.weight.bold, + normal: euiTheme.font.weight.regular, +}); + export const ToolbarButtonStyles = ({ euiTheme }: UseEuiTheme) => { return { + default: { + // style declaration carried over from https://github.com/elastic/kibana/blob/v8.10.4/src/plugins/kibana_react/public/toolbar_button/toolbar_button.scss + // informed by issue https://github.com/elastic/eui/issues/4730 + borderStyle: 'solid', + border: euiTheme.border.thin, + borderColor: euiTheme.border.color, + }, emptyButton: { backgroundColor: euiTheme.colors.emptyShade, - border: `${euiTheme.border.thin} !important`, + border: `${euiTheme.border.thin}`, color: `${euiTheme.colors.text}`, }, + buttonPositions: { + left: { + borderTopRightRadius: 0, + borderBottomRightRadius: 0, + }, + right: { + borderTopLeftRadius: 0, + borderBottomLeftRadius: 0, + borderLeft: 'none', + }, + center: { + borderRadius: 0, + borderLeft: 'none', + }, + }, }; }; diff --git a/packages/shared-ux/button_toolbar/src/buttons/toolbar_button/toolbar_button.test.tsx b/packages/shared-ux/button_toolbar/src/buttons/toolbar_button/toolbar_button.test.tsx index 74b5fde37f5ff..6761f4272079d 100644 --- a/packages/shared-ux/button_toolbar/src/buttons/toolbar_button/toolbar_button.test.tsx +++ b/packages/shared-ux/button_toolbar/src/buttons/toolbar_button/toolbar_button.test.tsx @@ -12,22 +12,47 @@ import { mountWithIntl } from '@kbn/test-jest-helpers'; import { ToolbarButton } from './toolbar_button'; describe('', () => { - test('is rendered - default', () => { - const component = mountWithIntl( 'click'} />); - expect(component.render()).toMatchSnapshot(); - }); + describe('standard', () => { + test('is rendered - default', () => { + const component = mountWithIntl( + 'click'} /> + ); + expect(component.render()).toMatchSnapshot(); + }); + + test('is rendered - primary', () => { + const component = mountWithIntl( + 'click'} /> + ); + expect(component.render()).toMatchSnapshot(); + }); + + test('is rendered - text wth icon', () => { + const component = mountWithIntl( + 'click'} + /> + ); + expect(component.render()).toMatchSnapshot(); + }); - test('is rendered - primary', () => { - const component = mountWithIntl( - 'click'} /> - ); - expect(component.render()).toMatchSnapshot(); + test('accepts an onClick handler', () => { + const mockHandler = jest.fn(); + const component = mountWithIntl(); + component.find('button').simulate('click'); + expect(mockHandler).toHaveBeenCalled(); + }); }); - test('accepts an onClick handler', () => { - const mockHandler = jest.fn(); - const component = mountWithIntl(); - component.find('button').simulate('click'); - expect(mockHandler).toHaveBeenCalled(); + describe('iconButton', () => { + test('is rendered - default', () => { + const component = mountWithIntl( + + ); + expect(component.render()).toMatchSnapshot(); + }); }); }); diff --git a/packages/shared-ux/button_toolbar/src/buttons/toolbar_button/toolbar_button.tsx b/packages/shared-ux/button_toolbar/src/buttons/toolbar_button/toolbar_button.tsx index 76adb41e237bd..84039857d0891 100644 --- a/packages/shared-ux/button_toolbar/src/buttons/toolbar_button/toolbar_button.tsx +++ b/packages/shared-ux/button_toolbar/src/buttons/toolbar_button/toolbar_button.tsx @@ -7,48 +7,177 @@ */ import React from 'react'; -import { EuiButton, useEuiTheme } from '@elastic/eui'; +import { EuiButton, EuiButtonIcon, useEuiTheme, IconType } from '@elastic/eui'; import { EuiButtonPropsForButton } from '@elastic/eui/src/components/button/button'; -import { ToolbarButtonStyles } from './toolbar_button.styles'; +import { ToolbarButtonStyles, fontWeightDefinitions } from './toolbar_button.styles'; type ToolbarButtonTypes = 'primary' | 'empty'; -/** - * Props for `PrimaryButton`. - */ -export interface Props +type ToolbarButtonFontWeights = 'normal' | 'bold'; + +type ButtonPositions = 'left' | 'right' | 'center' | 'none'; + +type ButtonRenderStyle = 'standard' | 'iconButton'; + +interface ToolbarButtonCommonProps extends Pick< EuiButtonPropsForButton, - 'onClick' | 'iconType' | 'iconSide' | 'size' | 'data-test-subj' | 'isDisabled' + 'onClick' | 'iconType' | 'size' | 'data-test-subj' | 'isDisabled' > { - label: string; + /** + * Render style of the toolbar button + */ + as?: ButtonRenderStyle; type?: ToolbarButtonTypes; + /** + * Adjusts the borders for groupings + */ + groupPosition?: ButtonPositions; } -export const ToolbarButton: React.FunctionComponent = ({ +type ToolbarStandardButton = Pick & + Omit & { + as?: Extract; + /** + * Display text for toolbar button + */ + label: React.ReactNode; + /** + * Determines if the button will have a down arrow or not + */ + hasArrow?: boolean; + /** + * Determines prominence + */ + fontWeight?: ToolbarButtonFontWeights; + }; + +type ToolbarIconButton = ToolbarButtonCommonProps & { + as: Extract; + iconType: IconType; + label?: string; +}; + +/** + * Props for `PrimaryButton`. + */ +export type Props = T extends Extract + ? ToolbarIconButton + : ToolbarStandardButton; + +const isIconButton = ( + props: ToolbarStandardButton | ToolbarIconButton +): props is ToolbarIconButton => { + return (props as ToolbarIconButton).as === 'iconButton'; +}; + +const computeToolbarButtonCommonCSSProps = ( + euiTheme: ReturnType, + { + type, + isDisabled, + groupPosition, + }: Pick, 'type' | 'isDisabled' | 'groupPosition'> +) => { + const toolButtonStyles = ToolbarButtonStyles(euiTheme); + + const groupPositionStyles = + groupPosition && groupPosition !== 'none' + ? toolButtonStyles.buttonPositions[groupPosition] + : {}; + + const defaultStyles = { + ...toolButtonStyles.default, + ...groupPositionStyles, + }; + + return isDisabled + ? defaultStyles + : { + ...defaultStyles, + ...(type === 'primary' ? {} : toolButtonStyles.emptyButton), + }; +}; + +const ToolbarStandardButton = ({ + hasArrow = true, + fontWeight = 'normal', + type, label, - type = 'empty', - iconSide = 'left', - size = 'm', + iconSide, + iconType, + fullWidth, isDisabled, + groupPosition, ...rest -}) => { +}: Omit) => { const euiTheme = useEuiTheme(); - const toolbarButtonStyleProps: EuiButtonPropsForButton = !isDisabled - ? type === 'primary' - ? { color: 'primary', fill: true } - : { color: 'text', css: ToolbarButtonStyles(euiTheme).emptyButton } - : {}; + const cssProps = { + ...computeToolbarButtonCommonCSSProps(euiTheme, { type, isDisabled, groupPosition }), + fontWeight: fontWeightDefinitions(euiTheme.euiTheme)[fontWeight], + }; + + const toolbarButtonStyleProps: EuiButtonPropsForButton = isDisabled + ? {} + : type === 'primary' + ? { color: 'primary', fill: true } + : { color: 'text' }; + + const icon = iconType ?? (hasArrow ? 'arrowDown' : ''); return ( {label} ); }; + +const ToolbarIconButton = ({ + size, + type, + label, + isDisabled, + groupPosition, + ...rest +}: Omit) => { + const euiTheme = useEuiTheme(); + const cssProps = computeToolbarButtonCommonCSSProps(euiTheme, { + type, + isDisabled, + groupPosition, + }); + + return ( + + ); +}; + +export function ToolbarButton(props: Props) { + const { type = 'empty', size = 'm' } = props; + + if (isIconButton(props)) { + return ; + } + + return ; +} diff --git a/packages/shared-ux/button_toolbar/src/popover/popover.test.tsx b/packages/shared-ux/button_toolbar/src/popover/popover.test.tsx index b03cb9e63d460..dfaba0f816e7e 100644 --- a/packages/shared-ux/button_toolbar/src/popover/popover.test.tsx +++ b/packages/shared-ux/button_toolbar/src/popover/popover.test.tsx @@ -37,7 +37,7 @@ describe('', () => { expect(button.prop('color')).toBe('text'); expect(button.prop('css')).toMatchObject({ backgroundColor: '#FFF', - border: '1px solid #D3DAE6 !important', + border: '1px solid #D3DAE6', color: '#343741', }); }); diff --git a/packages/shared-ux/button_toolbar/src/popover/popover.tsx b/packages/shared-ux/button_toolbar/src/popover/popover.tsx index 25dff5c52250f..c7af471b6eb48 100644 --- a/packages/shared-ux/button_toolbar/src/popover/popover.tsx +++ b/packages/shared-ux/button_toolbar/src/popover/popover.tsx @@ -12,7 +12,10 @@ import { Props as EuiPopoverProps } from '@elastic/eui/src/components/popover/po import { ToolbarButtonProps, ToolbarButton } from '../buttons'; -type AllowedButtonProps = Omit; +type AllowedButtonProps = Omit< + ToolbarButtonProps<'standard'>, + 'iconSide' | 'onClick' | 'fill' | 'label' +>; type AllowedPopoverProps = Omit< EuiPopoverProps, 'button' | 'isOpen' | 'closePopover' | 'anchorPosition' @@ -24,6 +27,7 @@ type AllowedPopoverProps = Omit< export type Props = AllowedButtonProps & AllowedPopoverProps & { children: (arg: { closePopover: () => void }) => React.ReactNode; + label: NonNullable['label']>; }; /** diff --git a/packages/shared-ux/button_toolbar/src/toolbar/__snapshots__/toolbar.test.tsx.snap b/packages/shared-ux/button_toolbar/src/toolbar/__snapshots__/toolbar.test.tsx.snap index 44b910bf017e7..32844b4bef9c6 100644 --- a/packages/shared-ux/button_toolbar/src/toolbar/__snapshots__/toolbar.test.tsx.snap +++ b/packages/shared-ux/button_toolbar/src/toolbar/__snapshots__/toolbar.test.tsx.snap @@ -8,7 +8,7 @@ exports[` is rendered 1`] = ` class="euiFlexItem emotion-euiFlexItem-growZero" >
diff --git a/src/cli/serve/integration_tests/serverless_config_flag.test.ts b/src/cli/serve/integration_tests/serverless_config_flag.test.ts index 9d20722ecbfc5..77c15f832081a 100644 --- a/src/cli/serve/integration_tests/serverless_config_flag.test.ts +++ b/src/cli/serve/integration_tests/serverless_config_flag.test.ts @@ -15,7 +15,10 @@ import { filter, firstValueFrom, from, concatMap } from 'rxjs'; import { REPO_ROOT } from '@kbn/repo-info'; import { getConfigDirectory } from '@kbn/utils'; -describe('cli serverless project type', () => { +// Failing: See https://github.com/elastic/kibana/issues/163257 +// Failing: See https://github.com/elastic/kibana/issues/163258 +// Failing: See https://github.com/elastic/kibana/issues/163259 +describe.skip('cli serverless project type', () => { let child: ChildProcessWithoutNullStreams | undefined; afterEach(() => { diff --git a/src/core/public/index.ts b/src/core/public/index.ts index b874a937257b2..6b29603dd63f6 100644 --- a/src/core/public/index.ts +++ b/src/core/public/index.ts @@ -187,6 +187,7 @@ export type { HttpResponse, HttpHandler, IBasePath, + IStaticAssets, IAnonymousPaths, IExternalUrl, IHttpInterceptController, diff --git a/src/core/server/index.ts b/src/core/server/index.ts index 30562d389ac41..3e63315e6d8fa 100644 --- a/src/core/server/index.ts +++ b/src/core/server/index.ts @@ -184,6 +184,7 @@ export type { ICspConfig, IExternalUrlConfig, IBasePath, + IStaticAssets, SessionStorage, SessionStorageCookieOptions, SessionCookieValidationResult, 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 dd736740a9377..2c7d540132139 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 @@ -125,9 +125,9 @@ describe('checking migration metadata changes on all registered SO types', () => "monitoring-telemetry": "5d91bf75787d9d4dd2fae954d0b3f76d33d2e559", "observability-onboarding-state": "b16064c516aac64ae699c737d7d10b6e199bfded", "osquery-manager-usage-metric": "983bcbc3b7dda0aad29b20907db233abba709bcc", - "osquery-pack": "6ab4358ca4304a12dcfc1777c8135b75cffb4397", - "osquery-pack-asset": "b14101d3172c4b60eb5404696881ce5275c84152", - "osquery-saved-query": "44f1161e165defe3f9b6ad643c68c542a765fcdb", + "osquery-pack": "702e86b1a936153b39f65b0781bdc136e186e123", + "osquery-pack-asset": "cd140bc2e4b092e93692b587bf6e38051ef94c75", + "osquery-saved-query": "6095e288750aa3164dfe186c74bc5195c2bf2bd4", "policy-settings-protection-updates-note": "33924bb246f9e5bcb876109cc83e3c7a28308352", "query": "21cbbaa09abb679078145ce90087b1e88b7eae95", "risk-engine-configuration": "b105d4a3c6adce40708d729d12e5ef3c8fbd9508", diff --git a/src/core/server/integration_tests/elasticsearch/error_logging.test.ts b/src/core/server/integration_tests/elasticsearch/error_logging.test.ts new file mode 100644 index 0000000000000..8cd4f5ae41134 --- /dev/null +++ b/src/core/server/integration_tests/elasticsearch/error_logging.test.ts @@ -0,0 +1,94 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may 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'; + +describe('Error logging', () => { + describe('ES client errors', () => { + let mockConsoleLog: jest.SpyInstance; + let esServer: TestElasticsearchUtils; + let kibanaServer: TestKibanaUtils; + + beforeAll(async () => { + mockConsoleLog = jest.spyOn(global.console, 'log'); + + const { startES, startKibana } = createTestServers({ + adjustTimeout: jest.setTimeout, + settings: { + kbn: { + logging: { + appenders: { + 'console-json': { + type: 'console', + layout: { + type: 'json', + }, + }, + }, + loggers: [{ name: 'console-json', appenders: ['console-json'], level: 'debug' }], + }, + }, + }, + }); + + esServer = await startES(); + kibanaServer = await startKibana(); + }); + + beforeEach(() => { + mockConsoleLog.mockClear(); + }); + + afterAll(async () => { + mockConsoleLog.mockRestore(); + await kibanaServer.stop(); + await esServer.stop(); + }); + + it('logs errors following the expected pattern for the json layout', async () => { + const esClient = kibanaServer.coreStart.elasticsearch.client.asInternalUser; + const logger = kibanaServer.root.logger.get('console-json'); + + try { + await esClient.search({ + index: '.kibana', + // @ts-expect-error yes this is invalid + query: { someInvalidQuery: { foo: 'bar' } }, + }); + expect('should have thrown').toEqual('but it did not'); + } catch (e) { + logger.info('logging elasticsearch error', e); + + const calls = mockConsoleLog.mock.calls; + const ourCall = calls + .map((call) => call[0]) + .find((call) => call.includes('logging elasticsearch error')); + + expect(JSON.parse(ourCall)).toEqual({ + '@timestamp': expect.any(String), + ecs: { + version: expect.any(String), + }, + log: { + level: 'INFO', + logger: 'console-json', + }, + message: 'logging elasticsearch error', + name: 'ResponseError', + process: { + pid: expect.any(Number), + }, + }); + } + }); + }); +}); diff --git a/src/core/server/integration_tests/elasticsearch/errors.test.ts b/src/core/server/integration_tests/elasticsearch/errors.test.ts index b9dcfb33a23a4..abefdc7bf356c 100644 --- a/src/core/server/integration_tests/elasticsearch/errors.test.ts +++ b/src/core/server/integration_tests/elasticsearch/errors.test.ts @@ -6,6 +6,7 @@ * Side Public License, v 1. */ +import { inspect } from 'util'; import { createTestServers, type TestElasticsearchUtils, @@ -67,4 +68,28 @@ describe('elasticsearch clients errors', () => { `); } }); + + it('has the proper inspect representation', async () => { + const esClient = kibanaServer.coreStart.elasticsearch.client.asInternalUser; + + try { + await esClient.search({ + index: '.kibana', + // @ts-expect-error yes this is invalid + query: { someInvalidQuery: { foo: 'bar' } }, + }); + expect('should have thrown').toEqual('but it did not'); + } catch (e) { + expect(inspect(e)).toMatchInlineSnapshot(` + "{ + name: 'ResponseError', + message: 'parsing_exception\\\\n' + + '\\\\tCaused by:\\\\n' + + '\\\\t\\\\tnamed_object_not_found_exception: [1:30] unknown field [someInvalidQuery]\\\\n' + + '\\\\tRoot causes:\\\\n' + + '\\\\t\\\\tparsing_exception: unknown query [someInvalidQuery]' + }" + `); + } + }); }); diff --git a/src/core/server/integration_tests/http/http_server.test.ts b/src/core/server/integration_tests/http/http_server.test.ts index f65a5b59487be..da10b231b7a22 100644 --- a/src/core/server/integration_tests/http/http_server.test.ts +++ b/src/core/server/integration_tests/http/http_server.test.ts @@ -36,6 +36,7 @@ describe('Http server', () => { allowFromAnyIp: true, ipAllowlist: [], }, + cdn: {}, cors: { enabled: false, }, diff --git a/src/core/server/integration_tests/ui_settings/routes.test.ts b/src/core/server/integration_tests/ui_settings/routes.test.ts index 6999731947d86..078946a7a9ab5 100644 --- a/src/core/server/integration_tests/ui_settings/routes.test.ts +++ b/src/core/server/integration_tests/ui_settings/routes.test.ts @@ -156,6 +156,47 @@ describe('ui settings service', () => { }); }); + describe('validate', () => { + it('returns correct validation error message for invalid value', async () => { + const response = await request + .post(root, '/internal/kibana/settings/custom/validate') + .send({ value: 100 }) + .expect(200); + + expect(response.body).toMatchObject({ + valid: false, + errorMessage: 'expected value of type [string] but got [number]', + }); + }); + + it('returns no validation error message for valid value', async () => { + const response = await request + .post(root, '/internal/kibana/settings/custom/validate') + .send({ value: 'test' }) + .expect(200); + + expect(response.body).toMatchObject({ valid: true }); + }); + + it('returns a 404 for non-existing key', async () => { + const response = await request + .post(root, '/internal/kibana/settings/test/validate') + .send({ value: 'test' }) + .expect(404); + + expect(response.body.message).toBe('Setting with a key [test] does not exist.'); + }); + + it('returns a 400 for a null value', async () => { + const response = await request + .post(root, '/internal/kibana/settings/test/validate') + .send({ value: null }) + .expect(400); + + expect(response.body.message).toBe('No value was specified.'); + }); + }); + describe('global', () => { describe('set', () => { it('validates value', async () => { diff --git a/src/plugins/advanced_settings/public/management_app/settings.test.tsx b/src/plugins/advanced_settings/public/management_app/settings.test.tsx index f51eec4e97bb6..a98b29922af1a 100644 --- a/src/plugins/advanced_settings/public/management_app/settings.test.tsx +++ b/src/plugins/advanced_settings/public/management_app/settings.test.tsx @@ -201,6 +201,8 @@ function mockConfig() { }, }; }, + validateValue: (key: string, value: any) => + Promise.resolve({ successfulValidation: true, valid: true }), }; return { core: { diff --git a/src/plugins/advanced_settings/public/management_app/settings_helper.test.ts b/src/plugins/advanced_settings/public/management_app/settings_helper.test.ts index 7f745db9b786b..e4aaab4bb3054 100644 --- a/src/plugins/advanced_settings/public/management_app/settings_helper.test.ts +++ b/src/plugins/advanced_settings/public/management_app/settings_helper.test.ts @@ -129,6 +129,8 @@ describe('Settings Helper', () => { ...imageSetting, }; }, + validateValue: (key: string, value: any) => + Promise.resolve({ successfulValidation: true, valid: true }), }; it('mapConfig', () => { diff --git a/src/plugins/advanced_settings/server/index.ts b/src/plugins/advanced_settings/server/index.ts index f78be24868a5c..de573ad54cd66 100644 --- a/src/plugins/advanced_settings/server/index.ts +++ b/src/plugins/advanced_settings/server/index.ts @@ -7,9 +7,10 @@ */ import { PluginInitializerContext } from '@kbn/core/server'; -import { AdvancedSettingsServerPlugin } from './plugin'; export { config } from './config'; -export const plugin = (initContext: PluginInitializerContext) => - new AdvancedSettingsServerPlugin(initContext); +export const plugin = async (initContext: PluginInitializerContext) => { + const { AdvancedSettingsServerPlugin } = await import('./plugin'); + return new AdvancedSettingsServerPlugin(initContext); +}; diff --git a/src/plugins/bfetch/server/index.ts b/src/plugins/bfetch/server/index.ts index f0e6b15f99758..6e477df550419 100644 --- a/src/plugins/bfetch/server/index.ts +++ b/src/plugins/bfetch/server/index.ts @@ -7,10 +7,10 @@ */ import { PluginInitializerContext } from '@kbn/core/server'; -import { BfetchServerPlugin } from './plugin'; export type { BfetchServerSetup, BfetchServerStart, BatchProcessingRouteParams } from './plugin'; -export function plugin(initializerContext: PluginInitializerContext) { +export async function plugin(initializerContext: PluginInitializerContext) { + const { BfetchServerPlugin } = await import('./plugin'); return new BfetchServerPlugin(initializerContext); } diff --git a/src/plugins/bfetch/server/mocks.ts b/src/plugins/bfetch/server/mocks.ts index d1be681dd407f..4fb5d1ea8eb58 100644 --- a/src/plugins/bfetch/server/mocks.ts +++ b/src/plugins/bfetch/server/mocks.ts @@ -31,7 +31,7 @@ const createPlugin = async () => { const pluginInitializerContext = coreMock.createPluginInitializerContext(); const coreSetup = coreMock.createSetup(); const coreStart = coreMock.createStart(); - const plugin = pluginInitializer(pluginInitializerContext); + const plugin = await pluginInitializer(pluginInitializerContext); const setup = await plugin.setup(coreSetup, {}); return { diff --git a/src/plugins/chart_expressions/expression_gauge/server/index.ts b/src/plugins/chart_expressions/expression_gauge/server/index.ts index b0539ab12b18c..9420c05feddf6 100644 --- a/src/plugins/chart_expressions/expression_gauge/server/index.ts +++ b/src/plugins/chart_expressions/expression_gauge/server/index.ts @@ -6,8 +6,7 @@ * Side Public License, v 1. */ -import { ExpressionGaugePlugin } from './plugin'; - -export function plugin() { +export async function plugin() { + const { ExpressionGaugePlugin } = await import('./plugin'); return new ExpressionGaugePlugin(); } diff --git a/src/plugins/chart_expressions/expression_heatmap/server/index.ts b/src/plugins/chart_expressions/expression_heatmap/server/index.ts index fbbf8027eb343..869886ca210f1 100644 --- a/src/plugins/chart_expressions/expression_heatmap/server/index.ts +++ b/src/plugins/chart_expressions/expression_heatmap/server/index.ts @@ -6,8 +6,7 @@ * Side Public License, v 1. */ -import { ExpressionHeatmapPlugin } from './plugin'; - -export function plugin() { +export async function plugin() { + const { ExpressionHeatmapPlugin } = await import('./plugin'); return new ExpressionHeatmapPlugin(); } diff --git a/src/plugins/chart_expressions/expression_legacy_metric/server/index.ts b/src/plugins/chart_expressions/expression_legacy_metric/server/index.ts index 9c9c1641b68a8..6053a916e2b96 100644 --- a/src/plugins/chart_expressions/expression_legacy_metric/server/index.ts +++ b/src/plugins/chart_expressions/expression_legacy_metric/server/index.ts @@ -6,8 +6,7 @@ * Side Public License, v 1. */ -import { ExpressionLegacyMetricPlugin } from './plugin'; - -export function plugin() { +export async function plugin() { + const { ExpressionLegacyMetricPlugin } = await import('./plugin'); return new ExpressionLegacyMetricPlugin(); } diff --git a/src/plugins/chart_expressions/expression_metric/server/index.ts b/src/plugins/chart_expressions/expression_metric/server/index.ts index dfb442514d5f0..8bdbfd5b4f372 100644 --- a/src/plugins/chart_expressions/expression_metric/server/index.ts +++ b/src/plugins/chart_expressions/expression_metric/server/index.ts @@ -6,8 +6,7 @@ * Side Public License, v 1. */ -import { ExpressionMetricPlugin } from './plugin'; - -export function plugin() { +export async function plugin() { + const { ExpressionMetricPlugin } = await import('./plugin'); return new ExpressionMetricPlugin(); } diff --git a/src/plugins/chart_expressions/expression_partition_vis/public/__mocks__/ui_settings.ts b/src/plugins/chart_expressions/expression_partition_vis/public/__mocks__/ui_settings.ts index 1585133e3b8d6..490d2c931b447 100644 --- a/src/plugins/chart_expressions/expression_partition_vis/public/__mocks__/ui_settings.ts +++ b/src/plugins/chart_expressions/expression_partition_vis/public/__mocks__/ui_settings.ts @@ -28,4 +28,6 @@ export const uiSettings: IUiSettingsClient = { getAll: (): Readonly> => { return {}; }, + validateValue: (key: string, value: any) => + Promise.resolve({ successfulValidation: true, valid: true }), }; diff --git a/src/plugins/chart_expressions/expression_partition_vis/server/index.ts b/src/plugins/chart_expressions/expression_partition_vis/server/index.ts index 98395d521e238..30a53f4cfb8d2 100755 --- a/src/plugins/chart_expressions/expression_partition_vis/server/index.ts +++ b/src/plugins/chart_expressions/expression_partition_vis/server/index.ts @@ -6,9 +6,8 @@ * Side Public License, v 1. */ -import { ExpressionPartitionVisPlugin } from './plugin'; - -export function plugin() { +export async function plugin() { + const { ExpressionPartitionVisPlugin } = await import('./plugin'); return new ExpressionPartitionVisPlugin(); } diff --git a/src/plugins/chart_expressions/expression_tagcloud/server/index.ts b/src/plugins/chart_expressions/expression_tagcloud/server/index.ts index c944168271314..337d6cdc636cb 100644 --- a/src/plugins/chart_expressions/expression_tagcloud/server/index.ts +++ b/src/plugins/chart_expressions/expression_tagcloud/server/index.ts @@ -6,8 +6,7 @@ * Side Public License, v 1. */ -import { ExpressionTagcloudPlugin } from './plugin'; - -export function plugin() { +export async function plugin() { + const { ExpressionTagcloudPlugin } = await import('./plugin'); return new ExpressionTagcloudPlugin(); } diff --git a/src/plugins/chart_expressions/expression_xy/server/index.ts b/src/plugins/chart_expressions/expression_xy/server/index.ts index e529b2a15fe34..453e9ed3dc3d6 100755 --- a/src/plugins/chart_expressions/expression_xy/server/index.ts +++ b/src/plugins/chart_expressions/expression_xy/server/index.ts @@ -6,9 +6,8 @@ * Side Public License, v 1. */ -import { ExpressionXyPlugin } from './plugin'; - -export function plugin() { +export async function plugin() { + const { ExpressionXyPlugin } = await import('./plugin'); return new ExpressionXyPlugin(); } diff --git a/src/plugins/charts/server/index.ts b/src/plugins/charts/server/index.ts index ec59c25b50e98..0317ad486c346 100644 --- a/src/plugins/charts/server/index.ts +++ b/src/plugins/charts/server/index.ts @@ -6,8 +6,10 @@ * Side Public License, v 1. */ -import { ChartsServerPlugin } from './plugin'; export type { CustomPaletteArguments, CustomPaletteState, SystemPaletteArguments } from '../common'; export { paletteIds } from '../common'; -export const plugin = () => new ChartsServerPlugin(); +export const plugin = async () => { + const { ChartsServerPlugin } = await import('./plugin'); + return new ChartsServerPlugin(); +}; diff --git a/src/plugins/console/server/index.ts b/src/plugins/console/server/index.ts index 84f0d5cbad250..5def502ed5a25 100644 --- a/src/plugins/console/server/index.ts +++ b/src/plugins/console/server/index.ts @@ -8,10 +8,12 @@ import { PluginInitializerContext } from '@kbn/core/server'; -import { ConsoleServerPlugin } from './plugin'; - export type { ConsoleSetup, ConsoleStart } from './types'; export { config } from './config'; -export const plugin = (ctx: PluginInitializerContext) => new ConsoleServerPlugin(ctx); +export const plugin = async (ctx: PluginInitializerContext) => { + const { ConsoleServerPlugin } = await import('./plugin'); + + return new ConsoleServerPlugin(ctx); +}; diff --git a/src/plugins/content_management/server/index.ts b/src/plugins/content_management/server/index.ts index cdd69cb99b296..3e8a540d3f6bb 100644 --- a/src/plugins/content_management/server/index.ts +++ b/src/plugins/content_management/server/index.ts @@ -7,9 +7,8 @@ */ import type { PluginInitializerContext } from '@kbn/core/server'; -import { ContentManagementPlugin } from './plugin'; - -export function plugin(initializerContext: PluginInitializerContext) { +export async function plugin(initializerContext: PluginInitializerContext) { + const { ContentManagementPlugin } = await import('./plugin'); return new ContentManagementPlugin(initializerContext); } diff --git a/src/plugins/controls/server/index.ts b/src/plugins/controls/server/index.ts index cec761ae80e20..e003036dc8f47 100644 --- a/src/plugins/controls/server/index.ts +++ b/src/plugins/controls/server/index.ts @@ -6,8 +6,9 @@ * Side Public License, v 1. */ -import { ControlsPlugin } from './plugin'; - -export const plugin = () => new ControlsPlugin(); +export const plugin = async () => { + const { ControlsPlugin } = await import('./plugin'); + return new ControlsPlugin(); +}; export { initializeControlGroupTelemetry } from './control_group/control_group_telemetry'; diff --git a/src/plugins/custom_integrations/server/index.ts b/src/plugins/custom_integrations/server/index.ts index 95e181903e973..dcca939d117ce 100755 --- a/src/plugins/custom_integrations/server/index.ts +++ b/src/plugins/custom_integrations/server/index.ts @@ -8,12 +8,12 @@ import { schema } from '@kbn/config-schema'; import { PluginInitializerContext } from '@kbn/core/server'; -import { CustomIntegrationsPlugin } from './plugin'; // This exports static code and TypeScript types, // as well as, Kibana Platform `plugin()` initializer. -export function plugin(initializerContext: PluginInitializerContext) { +export async function plugin(initializerContext: PluginInitializerContext) { + const { CustomIntegrationsPlugin } = await import('./plugin'); return new CustomIntegrationsPlugin(initializerContext); } diff --git a/src/plugins/dashboard/public/dashboard_container/external_api/dashboard_renderer.test.tsx b/src/plugins/dashboard/public/dashboard_container/external_api/dashboard_renderer.test.tsx index 5ba29031d5cb7..529f13dc261ff 100644 --- a/src/plugins/dashboard/public/dashboard_container/external_api/dashboard_renderer.test.tsx +++ b/src/plugins/dashboard/public/dashboard_container/external_api/dashboard_renderer.test.tsx @@ -11,6 +11,7 @@ import { ReactWrapper } from 'enzyme'; import { act } from 'react-dom/test-utils'; import { mountWithIntl } from '@kbn/test-jest-helpers'; import { NotFoundPrompt } from '@kbn/shared-ux-prompt-not-found'; +import { setStubKibanaServices } from '@kbn/embeddable-plugin/public/mocks'; import { DashboardContainerFactory } from '..'; import { DASHBOARD_CONTAINER_TYPE } from '../..'; @@ -168,6 +169,9 @@ describe('dashboard renderer', () => { }); test('renders a 404 page when initial dashboard creation returns a savedObjectNotFound error', async () => { + // mock embeddable dependencies so that the embeddable panel renders + setStubKibanaServices(); + // ensure that the first attempt at creating a dashboard results in a 404 const mockErrorEmbeddable = { error: new SavedObjectNotFound('dashboard', 'gat em'), diff --git a/src/plugins/dashboard/server/index.ts b/src/plugins/dashboard/server/index.ts index 8dbc074fefa59..a1ac1e5d0fd9c 100644 --- a/src/plugins/dashboard/server/index.ts +++ b/src/plugins/dashboard/server/index.ts @@ -7,7 +7,6 @@ */ import { PluginInitializerContext, PluginConfigDescriptor } from '@kbn/core/server'; -import { DashboardPlugin } from './plugin'; import { configSchema, ConfigSchema } from '../config'; export const config: PluginConfigDescriptor = { @@ -20,7 +19,8 @@ export const config: PluginConfigDescriptor = { // This exports static code and TypeScript types, // as well as, Kibana Platform `plugin()` initializer. -export function plugin(initializerContext: PluginInitializerContext) { +export async function plugin(initializerContext: PluginInitializerContext) { + const { DashboardPlugin } = await import('./plugin'); return new DashboardPlugin(initializerContext); } diff --git a/src/plugins/data/common/search/search_source/fetch/get_search_params.test.ts b/src/plugins/data/common/search/search_source/fetch/get_search_params.test.ts index 1a517bf64d13b..975ad8d4a4878 100644 --- a/src/plugins/data/common/search/search_source/fetch/get_search_params.test.ts +++ b/src/plugins/data/common/search/search_source/fetch/get_search_params.test.ts @@ -9,6 +9,7 @@ import { UI_SETTINGS } from '../../../constants'; import { GetConfigFn } from '../../../types'; import { getSearchParams, getSearchParamsFromRequest } from './get_search_params'; +import { createStubDataView } from '@kbn/data-views-plugin/common/data_views/data_view.stub'; function getConfigStub(config: any = {}): GetConfigFn { return (key) => config[key]; @@ -46,4 +47,50 @@ describe('getSearchParams', () => { query: 123, }); }); + + test('sets expand_wildcards=all if data view has allowHidden=true', () => { + const getConfig = getConfigStub({ + [UI_SETTINGS.COURIER_SET_REQUEST_PREFERENCE]: 'custom', + [UI_SETTINGS.COURIER_CUSTOM_REQUEST_PREFERENCE]: 'aaa', + }); + const index = createStubDataView({ + spec: { + allowHidden: true, + }, + }); + const searchParams = getSearchParamsFromRequest( + { + index, + body: { + query: 123, + track_total_hits: true, + }, + }, + { getConfig } + ); + expect(searchParams).toHaveProperty('expand_wildcards', 'all'); + }); + + test('does not set expand_wildcards if data view has allowHidden=false', () => { + const getConfig = getConfigStub({ + [UI_SETTINGS.COURIER_SET_REQUEST_PREFERENCE]: 'custom', + [UI_SETTINGS.COURIER_CUSTOM_REQUEST_PREFERENCE]: 'aaa', + }); + const index = createStubDataView({ + spec: { + allowHidden: false, + }, + }); + const searchParams = getSearchParamsFromRequest( + { + index, + body: { + query: 123, + track_total_hits: true, + }, + }, + { getConfig } + ); + expect(searchParams).not.toHaveProperty('expand_wildcards', 'all'); + }); }); diff --git a/src/plugins/data/common/search/search_source/fetch/get_search_params.ts b/src/plugins/data/common/search/search_source/fetch/get_search_params.ts index 5f8ca973b3dfe..db630c85177e3 100644 --- a/src/plugins/data/common/search/search_source/fetch/get_search_params.ts +++ b/src/plugins/data/common/search/search_source/fetch/get_search_params.ts @@ -42,8 +42,8 @@ export function getSearchParamsFromRequest( return { index: searchRequest.index.title || searchRequest.index, body, - // @ts-expect-error `track_total_hits` not allowed at top level for `typesWithBodyKey` track_total_hits, + ...(searchRequest.index?.allowHidden && { expand_wildcards: 'all' }), ...searchParams, }; } diff --git a/src/plugins/data/common/search/strategies/ese_search/types.ts b/src/plugins/data/common/search/strategies/ese_search/types.ts index 69812cdeae07b..c54d6f3216f36 100644 --- a/src/plugins/data/common/search/strategies/ese_search/types.ts +++ b/src/plugins/data/common/search/strategies/ese_search/types.ts @@ -6,11 +6,11 @@ * Side Public License, v 1. */ -import { ISearchOptions } from '../../types'; +import { SearchSourceSearchOptions } from '../../search_source/types'; export const ENHANCED_ES_SEARCH_STRATEGY = 'ese'; -export interface IAsyncSearchOptions extends ISearchOptions { +export interface IAsyncSearchOptions extends SearchSourceSearchOptions { /** * The number of milliseconds to wait between receiving a response and sending another request * If not provided, then a default 1 second interval with back-off up to 5 seconds interval is used diff --git a/src/plugins/data/config.ts b/src/plugins/data/config.ts index 03cd77653becb..b6adfdede2469 100644 --- a/src/plugins/data/config.ts +++ b/src/plugins/data/config.ts @@ -86,6 +86,10 @@ export const searchConfigSchema = schema.object({ export const configSchema = schema.object({ search: searchConfigSchema, + /** + * Turns on/off limit validations for the registered uiSettings. + */ + enableUiSettingsValidations: schema.boolean({ defaultValue: false }), }); export type ConfigSchema = TypeOf; diff --git a/src/plugins/data/public/search/errors/es_error.test.tsx b/src/plugins/data/public/search/errors/es_error.test.tsx index 1b7f57d24d4f9..7f82faf685aba 100644 --- a/src/plugins/data/public/search/errors/es_error.test.tsx +++ b/src/plugins/data/public/search/errors/es_error.test.tsx @@ -21,7 +21,7 @@ describe('EsError', () => { }, }, } as IEsError; - const esError = new EsError(error); + const esError = new EsError(error, () => {}); expect(typeof esError.attributes).toEqual('object'); expect(esError.attributes).toEqual(error.attributes); @@ -50,7 +50,7 @@ describe('EsError', () => { }, }, } as IEsError; - const esError = new EsError(error); + const esError = new EsError(error, () => {}); expect(esError.message).toEqual( 'EsError: The supplied interval [2q] could not be parsed as a calendar interval.' ); diff --git a/src/plugins/data/public/search/errors/es_error.tsx b/src/plugins/data/public/search/errors/es_error.tsx index 34d074a427187..f5b978b38bc1e 100644 --- a/src/plugins/data/public/search/errors/es_error.tsx +++ b/src/plugins/data/public/search/errors/es_error.tsx @@ -7,7 +7,7 @@ */ import React from 'react'; -import { EuiCodeBlock, EuiSpacer } from '@elastic/eui'; +import { EuiButton, EuiCodeBlock, EuiSpacer } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { ApplicationStart } from '@kbn/core/public'; import { KbnError } from '@kbn/kibana-utils-plugin/common'; @@ -17,7 +17,7 @@ import { getRootCause } from './utils'; export class EsError extends KbnError { readonly attributes: IEsError['attributes']; - constructor(protected readonly err: IEsError) { + constructor(protected readonly err: IEsError, private readonly openInInspector: () => void) { super( `EsError: ${ getRootCause(err?.attributes?.error)?.reason || @@ -27,7 +27,7 @@ export class EsError extends KbnError { this.attributes = err.attributes; } - public getErrorMessage(application: ApplicationStart) { + public getErrorMessage() { if (!this.attributes?.error) { return null; } @@ -45,4 +45,14 @@ export class EsError extends KbnError { ); } + + public getActions(application: ApplicationStart) { + return [ + + {i18n.translate('data.esError.viewDetailsButtonLabel', { + defaultMessage: 'View details', + })} + , + ]; + } } diff --git a/src/plugins/data/public/search/errors/painless_error.test.tsx b/src/plugins/data/public/search/errors/painless_error.test.tsx index 4bf79a6f5b5d9..03d4180b2aaac 100644 --- a/src/plugins/data/public/search/errors/painless_error.test.tsx +++ b/src/plugins/data/public/search/errors/painless_error.test.tsx @@ -20,14 +20,17 @@ describe('PainlessError', () => { }); it('Should show reason and code', () => { - const e = new PainlessError({ - statusCode: 400, - message: 'search_phase_execution_exception', - attributes: { - error: searchPhaseException.error, + const e = new PainlessError( + { + statusCode: 400, + message: 'search_phase_execution_exception', + attributes: { + error: searchPhaseException.error, + }, }, - }); - const component = mount(e.getErrorMessage(startMock.application)); + () => {} + ); + const component = mount(e.getErrorMessage()); const failedShards = searchPhaseException.error.failed_shards![0]; @@ -41,6 +44,7 @@ describe('PainlessError', () => { ).getDOMNode(); expect(humanReadableError.textContent).toBe(failedShards?.reason.caused_by?.reason); - expect(component.find('EuiButton').length).toBe(1); + const actions = e.getActions(startMock.application); + expect(actions.length).toBe(2); }); }); diff --git a/src/plugins/data/public/search/errors/painless_error.tsx b/src/plugins/data/public/search/errors/painless_error.tsx index 0435256f595cf..e76adddfb0815 100644 --- a/src/plugins/data/public/search/errors/painless_error.tsx +++ b/src/plugins/data/public/search/errors/painless_error.tsx @@ -8,8 +8,7 @@ import React from 'react'; import { i18n } from '@kbn/i18n'; -import { EuiButton, EuiSpacer, EuiText, EuiCodeBlock } from '@elastic/eui'; -import { FormattedMessage } from '@kbn/i18n-react'; +import { EuiButtonEmpty, EuiSpacer, EuiText, EuiCodeBlock } from '@elastic/eui'; import { ApplicationStart } from '@kbn/core/public'; import type { DataView } from '@kbn/data-views-plugin/common'; import { IEsError, isEsError } from './types'; @@ -19,18 +18,12 @@ import { getRootCause } from './utils'; export class PainlessError extends EsError { painlessStack?: string; indexPattern?: DataView; - constructor(err: IEsError, indexPattern?: DataView) { - super(err); + constructor(err: IEsError, openInInspector: () => void, indexPattern?: DataView) { + super(err, openInInspector); this.indexPattern = indexPattern; } - public getErrorMessage(application: ApplicationStart) { - function onClick(indexPatternId?: string) { - application.navigateToApp('management', { - path: `/kibana/indexPatterns${indexPatternId ? `/patterns/${indexPatternId}` : ''}`, - }); - } - + public getErrorMessage() { const rootCause = getRootCause(this.err.attributes?.error); const scriptFromStackTrace = rootCause?.script_stack ? rootCause?.script_stack?.slice(-2).join('\n') @@ -41,7 +34,6 @@ export class PainlessError extends EsError { // fallback, show ES stacktrace const painlessStack = rootCause?.script_stack ? rootCause?.script_stack.join('\n') : undefined; - const indexPatternId = this?.indexPattern?.id; return ( <> @@ -54,25 +46,40 @@ export class PainlessError extends EsError { })} - {scriptFromStackTrace || painlessStack ? ( {hasScript ? scriptFromStackTrace : painlessStack} ) : null} {humanReadableError ? ( - {humanReadableError} + + {humanReadableError} + ) : null} - - - - onClick(indexPatternId)} size="s"> - - - ); } + + getActions(application: ApplicationStart) { + function onClick(indexPatternId?: string) { + application.navigateToApp('management', { + path: `/kibana/indexPatterns${indexPatternId ? `/patterns/${indexPatternId}` : ''}`, + }); + } + const actions = super.getActions(application) ?? []; + actions.push( + onClick(this?.indexPattern?.id)} + size="s" + > + {i18n.translate('data.painlessError.buttonTxt', { + defaultMessage: 'Edit script', + })} + + ); + return actions; + } } export function isPainlessError(err: Error | IEsError) { diff --git a/src/plugins/data/public/search/search_interceptor/search_interceptor.test.ts b/src/plugins/data/public/search/search_interceptor/search_interceptor.test.ts index 013afb428931d..09db89ee74a0e 100644 --- a/src/plugins/data/public/search/search_interceptor/search_interceptor.test.ts +++ b/src/plugins/data/public/search/search_interceptor/search_interceptor.test.ts @@ -23,6 +23,8 @@ import { BehaviorSubject } from 'rxjs'; import { dataPluginMock } from '../../mocks'; import { UI_SETTINGS } from '../../../common'; import type { IEsError } from '../errors'; +import type { SearchServiceStartDependencies } from '../search_service'; +import type { Start as InspectorStart } from '@kbn/inspector-plugin/public'; jest.mock('./utils', () => { const originalModule = jest.requireActual('./utils'); @@ -117,13 +119,21 @@ describe('SearchInterceptor', () => { const bfetchMock = bfetchPluginMock.createSetupContract(); bfetchMock.batchedFunction.mockReturnValue(fetchMock); + const inspectorServiceMock = { + open: () => {}, + } as unknown as InspectorStart; + bfetchSetup = bfetchPluginMock.createSetupContract(); bfetchSetup.batchedFunction.mockReturnValue(fetchMock); searchInterceptor = new SearchInterceptor({ bfetch: bfetchSetup, toasts: mockCoreSetup.notifications.toasts, startServices: new Promise((resolve) => { - resolve([mockCoreStart, {}, {}]); + resolve([ + mockCoreStart, + { inspector: inspectorServiceMock } as unknown as SearchServiceStartDependencies, + {}, + ]); }), uiSettings: mockCoreSetup.uiSettings, http: mockCoreSetup.http, @@ -149,13 +159,16 @@ describe('SearchInterceptor', () => { test('Renders a PainlessError', async () => { searchInterceptor.showError( - new PainlessError({ - statusCode: 400, - message: 'search_phase_execution_exception', - attributes: { - error: searchPhaseException.error, + new PainlessError( + { + statusCode: 400, + message: 'search_phase_execution_exception', + attributes: { + error: searchPhaseException.error, + }, }, - }) + () => {} + ) ); expect(mockCoreSetup.notifications.toasts.addDanger).toBeCalledTimes(1); expect(mockCoreSetup.notifications.toasts.addError).not.toBeCalled(); diff --git a/src/plugins/data/public/search/search_interceptor/search_interceptor.ts b/src/plugins/data/public/search/search_interceptor/search_interceptor.ts index 5aebc455ad5b6..68dca8f4d0304 100644 --- a/src/plugins/data/public/search/search_interceptor/search_interceptor.ts +++ b/src/plugins/data/public/search/search_interceptor/search_interceptor.ts @@ -6,6 +6,7 @@ * Side Public License, v 1. */ +import { v4 as uuidv4 } from 'uuid'; import { memoize, once } from 'lodash'; import { BehaviorSubject, @@ -29,9 +30,12 @@ import { takeUntil, tap, } from 'rxjs/operators'; +import { estypes } from '@elastic/elasticsearch'; +import { i18n } from '@kbn/i18n'; import { PublicMethodsOf } from '@kbn/utility-types'; import type { HttpSetup, IHttpFetchError } from '@kbn/core-http-browser'; import { BfetchRequestError } from '@kbn/bfetch-plugin/public'; +import { type Start as InspectorStart, RequestAdapter } from '@kbn/inspector-plugin/public'; import { ApplicationStart, @@ -73,13 +77,14 @@ import { SearchResponseCache } from './search_response_cache'; import { createRequestHash, getSearchErrorOverrideDisplay } from './utils'; import { SearchAbortController } from './search_abort_controller'; import { SearchConfigSchema } from '../../../config'; +import type { SearchServiceStartDependencies } from '../search_service'; export interface SearchInterceptorDeps { bfetch: BfetchPublicSetup; http: HttpSetup; executionContext: ExecutionContextSetup; uiSettings: IUiSettingsClient; - startServices: Promise<[CoreStart, any, unknown]>; + startServices: Promise<[CoreStart, object, unknown]>; toasts: ToastsSetup; usageCollector?: SearchUsageCollector; session: ISessionService; @@ -114,6 +119,7 @@ export class SearchInterceptor { { request: IKibanaSearchRequest; options: ISearchOptionsSerializable }, IKibanaSearchResponse >; + private inspector!: InspectorStart; /* * @internal @@ -121,9 +127,10 @@ export class SearchInterceptor { constructor(private readonly deps: SearchInterceptorDeps) { this.deps.http.addLoadingCountSource(this.pendingCount$); - this.deps.startServices.then(([coreStart]) => { + this.deps.startServices.then(([coreStart, depsStart]) => { this.application = coreStart.application; this.docLinks = coreStart.docLinks; + this.inspector = (depsStart as SearchServiceStartDependencies).inspector; }); this.batchedFetch = deps.bfetch.batchedFunction({ @@ -184,7 +191,8 @@ export class SearchInterceptor { */ private handleSearchError( e: KibanaServerError | AbortError, - options?: ISearchOptions, + requestBody: estypes.SearchRequest, + options?: IAsyncSearchOptions, isTimeout?: boolean ): Error { if (isTimeout || e.message === 'Request timed out') { @@ -203,7 +211,36 @@ export class SearchInterceptor { } if (isEsError(e)) { - return isPainlessError(e) ? new PainlessError(e, options?.indexPattern) : new EsError(e); + const openInInspector = () => { + const requestId = options?.inspector?.id ?? uuidv4(); + const requestAdapter = options?.inspector?.adapter ?? new RequestAdapter(); + if (!options?.inspector?.adapter) { + const requestResponder = requestAdapter.start( + i18n.translate('data.searchService.anonymousRequestTitle', { + defaultMessage: 'Request', + }), + { + id: requestId, + } + ); + requestResponder.json(requestBody); + requestResponder.error({ json: e.attributes }); + } + this.inspector.open( + { + requests: requestAdapter, + }, + { + options: { + initialRequestId: requestId, + initialTabs: ['clusters', 'response'], + }, + } + ); + }; + return isPainlessError(e) + ? new PainlessError(e, openInInspector, options?.indexPattern) + : new EsError(e, openInInspector); } return e instanceof Error ? e : new Error(e.message); @@ -473,7 +510,12 @@ export class SearchInterceptor { takeUntil(aborted$), catchError((e) => { return throwError( - this.handleSearchError(e, searchOptions, searchAbortController.isTimeout()) + this.handleSearchError( + e, + request?.params?.body ?? {}, + searchOptions, + searchAbortController.isTimeout() + ) ); }), tap((response) => { diff --git a/src/plugins/data/public/search/search_interceptor/utils.ts b/src/plugins/data/public/search/search_interceptor/utils.ts index c36a5ded6a2e8..f31e816de5267 100644 --- a/src/plugins/data/public/search/search_interceptor/utils.ts +++ b/src/plugins/data/public/search/search_interceptor/utils.ts @@ -24,13 +24,14 @@ export function getSearchErrorOverrideDisplay({ }: { error: Error; application: ApplicationStart; -}): { title: string; body: ReactNode } | undefined { +}): { title: string; body: ReactNode; actions?: ReactNode[] } | undefined { if (error instanceof EsError) { return { title: i18n.translate('data.search.esErrorTitle', { defaultMessage: 'Cannot retrieve search results', }), - body: error.getErrorMessage(application), + body: error.getErrorMessage(), + actions: error.getActions(application), }; } diff --git a/src/plugins/data/server/index.ts b/src/plugins/data/server/index.ts index 10368bd74281f..2f077e907dfca 100644 --- a/src/plugins/data/server/index.ts +++ b/src/plugins/data/server/index.ts @@ -8,7 +8,7 @@ import { PluginConfigDescriptor, PluginInitializerContext } from '@kbn/core/server'; import { ConfigSchema, configSchema } from '../config'; -import { DataServerPlugin, DataPluginSetup, DataPluginStart } from './plugin'; +import type { DataServerPlugin, DataPluginSetup, DataPluginStart } from './plugin'; export { getEsQueryConfig, DEFAULT_QUERY_LANGUAGE } from '../common'; @@ -101,12 +101,13 @@ export { getTime, parseInterval } from '../common'; * @public */ -export function plugin(initializerContext: PluginInitializerContext) { +export async function plugin(initializerContext: PluginInitializerContext) { + const { DataServerPlugin } = await import('./plugin'); return new DataServerPlugin(initializerContext); } export type { DataPluginSetup as PluginSetup, DataPluginStart as PluginStart }; -export { DataServerPlugin as Plugin }; +export type { DataServerPlugin as Plugin }; export const config: PluginConfigDescriptor = { deprecations: configDeprecationProvider, diff --git a/src/plugins/data/server/plugin.ts b/src/plugins/data/server/plugin.ts index 1b2b0c3c78ca1..dfe88a12026bb 100644 --- a/src/plugins/data/server/plugin.ts +++ b/src/plugins/data/server/plugin.ts @@ -74,9 +74,11 @@ export class DataServerPlugin private readonly kqlTelemetryService: KqlTelemetryService; private readonly queryService = new QueryService(); private readonly logger: Logger; + private readonly config: ConfigSchema; constructor(initializerContext: PluginInitializerContext) { this.logger = initializerContext.logger.get('data'); + this.config = initializerContext.config.get(); this.searchService = new SearchService(initializerContext, this.logger); this.scriptsService = new ScriptsService(); this.kqlTelemetryService = new KqlTelemetryService(initializerContext); @@ -90,7 +92,7 @@ export class DataServerPlugin const querySetup = this.queryService.setup(core); this.kqlTelemetryService.setup(core, { usageCollection }); - core.uiSettings.register(getUiSettings(core.docLinks)); + core.uiSettings.register(getUiSettings(core.docLinks, this.config.enableUiSettingsValidations)); const searchSetup = this.searchService.setup(core, { bfetch, diff --git a/src/plugins/data/server/ui_settings.ts b/src/plugins/data/server/ui_settings.ts index 3ed2a86fb0533..7b386e864fbc1 100644 --- a/src/plugins/data/server/ui_settings.ts +++ b/src/plugins/data/server/ui_settings.ts @@ -32,7 +32,8 @@ const requestPreferenceOptionLabels = { }; export function getUiSettings( - docLinks: DocLinksServiceSetup + docLinks: DocLinksServiceSetup, + enableValidations: boolean ): Record> { return { [UI_SETTINGS.META_FIELDS]: { @@ -463,13 +464,22 @@ export function getUiSettings( '', }, }), - schema: schema.arrayOf( - schema.object({ - from: schema.string(), - to: schema.string(), - display: schema.string(), - }) - ), + schema: enableValidations + ? schema.arrayOf( + schema.object({ + from: schema.string(), + to: schema.string(), + display: schema.string(), + }), + { maxSize: 10 } + ) + : schema.arrayOf( + schema.object({ + from: schema.string(), + to: schema.string(), + display: schema.string(), + }) + ), }, [UI_SETTINGS.FILTERS_PINNED_BY_DEFAULT]: { name: i18n.translate('data.advancedSettings.pinFiltersTitle', { diff --git a/src/plugins/data_view_editor/public/components/advanced_params_content/advanced_params_content.tsx b/src/plugins/data_view_editor/public/components/advanced_params_content/advanced_params_content.tsx index dcb8e2c1e1d80..db3746d02dc66 100644 --- a/src/plugins/data_view_editor/public/components/advanced_params_content/advanced_params_content.tsx +++ b/src/plugins/data_view_editor/public/components/advanced_params_content/advanced_params_content.tsx @@ -30,14 +30,16 @@ interface AdvancedParamsContentProps { disableAllowHidden: boolean; disableId: boolean; onAllowHiddenChange?: (value: boolean) => void; + defaultVisible?: boolean; } export const AdvancedParamsContent = ({ disableAllowHidden, disableId, onAllowHiddenChange, + defaultVisible = false, }: AdvancedParamsContentProps) => ( - + diff --git a/src/plugins/data_view_editor/public/components/advanced_params_content/advanced_params_section.tsx b/src/plugins/data_view_editor/public/components/advanced_params_content/advanced_params_section.tsx index b313fddb8ee2d..ce52223413ecd 100644 --- a/src/plugins/data_view_editor/public/components/advanced_params_content/advanced_params_section.tsx +++ b/src/plugins/data_view_editor/public/components/advanced_params_content/advanced_params_section.tsx @@ -13,10 +13,11 @@ import { EuiButtonEmpty, EuiSpacer } from '@elastic/eui'; interface Props { children: React.ReactNode; + defaultVisible: boolean; } -export const AdvancedParamsSection = ({ children }: Props) => { - const [isVisible, setIsVisible] = useState(false); +export const AdvancedParamsSection = ({ children, defaultVisible = false }: Props) => { + const [isVisible, setIsVisible] = useState(defaultVisible); const toggleIsVisible = useCallback(() => { setIsVisible(!isVisible); diff --git a/src/plugins/data_view_editor/public/components/data_view_editor_flyout_content.tsx b/src/plugins/data_view_editor/public/components/data_view_editor_flyout_content.tsx index ad344d482c0cf..73432737f9321 100644 --- a/src/plugins/data_view_editor/public/components/data_view_editor_flyout_content.tsx +++ b/src/plugins/data_view_editor/public/components/data_view_editor_flyout_content.tsx @@ -105,6 +105,7 @@ const IndexPatternEditorFlyoutContentComponent = ({ title: editData.getIndexPattern(), id: editData.id, name: editData.name, + allowHidden: editData.getAllowHidden(), ...(editData.timeFieldName ? { timestampField: { label: editData.timeFieldName, value: editData.timeFieldName }, @@ -124,6 +125,7 @@ const IndexPatternEditorFlyoutContentComponent = ({ timeFieldName: formData.timestampField?.value, id: formData.id, name: formData.name, + allowHidden: formData.allowHidden, }; if (type === INDEX_PATTERN_TYPE.ROLLUP && rollupIndex) { @@ -293,6 +295,7 @@ const IndexPatternEditorFlyoutContentComponent = ({ onAllowHiddenChange={() => { form.getFields().title.validate(); }} + defaultVisible={editData?.getAllowHidden()} />
this.allowHidden; + + setAllowHidden = (allowHidden: boolean) => (this.allowHidden = allowHidden); + /** * Get name of Data View */ @@ -325,6 +332,7 @@ export abstract class AbstractDataView { allowNoIndex: this.allowNoIndex ? this.allowNoIndex : undefined, runtimeFieldMap: stringifyOrUndefined(this.runtimeFieldMap), name: this.name, + allowHidden: this.allowHidden, }; } diff --git a/src/plugins/data_views/common/data_views/data_view.ts b/src/plugins/data_views/common/data_views/data_view.ts index 27681021757ff..f47d4c0fb2177 100644 --- a/src/plugins/data_views/common/data_views/data_view.ts +++ b/src/plugins/data_views/common/data_views/data_view.ts @@ -160,6 +160,7 @@ export class DataView extends AbstractDataView implements DataViewBase { fieldAttrs, allowNoIndex: this.allowNoIndex, name: this.name, + allowHidden: this.getAllowHidden(), }; // Filter undefined values from the spec diff --git a/src/plugins/data_views/common/data_views/data_views.ts b/src/plugins/data_views/common/data_views/data_views.ts index 7ec161e689e76..6052be19d4f99 100644 --- a/src/plugins/data_views/common/data_views/data_views.ts +++ b/src/plugins/data_views/common/data_views/data_views.ts @@ -531,6 +531,8 @@ export class DataViewsService { allowNoIndex: true, ...options, pattern: indexPattern.title as string, + allowHidden: + (indexPattern as DataViewSpec).allowHidden || (indexPattern as DataView)?.getAllowHidden(), }); private getFieldsAndIndicesForDataView = async (dataView: DataView) => { @@ -541,6 +543,7 @@ export class DataViewsService { allowNoIndex: true, pattern: dataView.getIndexPattern(), metaFields, + allowHidden: dataView.getAllowHidden(), }); }; @@ -553,6 +556,7 @@ export class DataViewsService { rollupIndex: options.rollupIndex, allowNoIndex: true, indexFilter: options.indexFilter, + allowHidden: options.allowHidden, }); }; @@ -704,6 +708,7 @@ export class DataViewsService { fieldAttrs, allowNoIndex, name, + allowHidden, }, } = savedObject; @@ -731,6 +736,7 @@ export class DataViewsService { allowNoIndex, runtimeFieldMap: parsedRuntimeFieldMap, name, + allowHidden, }; }; @@ -763,6 +769,7 @@ export class DataViewsService { type, rollupIndex: typeMeta?.params?.rollup_index, allowNoIndex: spec.allowNoIndex, + allowHidden: spec.allowHidden, }, spec.fieldAttrs, displayErrors diff --git a/src/plugins/data_views/common/types.ts b/src/plugins/data_views/common/types.ts index 79a2524a4d80c..dc477d2fb5b83 100644 --- a/src/plugins/data_views/common/types.ts +++ b/src/plugins/data_views/common/types.ts @@ -157,6 +157,10 @@ export interface DataViewAttributes { * Name of the data view. Human readable name used to differentiate data view. */ name?: string; + /** + * Allow hidden and system indices when loading field list + */ + allowHidden?: boolean; } /** @@ -309,6 +313,7 @@ export interface GetFieldsOptions { indexFilter?: QueryDslQueryContainer; includeUnmapped?: boolean; fields?: string[]; + allowHidden?: boolean; } /** @@ -517,6 +522,10 @@ export type DataViewSpec = { * Name of the data view. Human readable name used to differentiate data view. */ name?: string; + /** + * Allow hidden and system indices when loading field list + */ + allowHidden?: boolean; }; // eslint-disable-next-line @typescript-eslint/consistent-type-definitions diff --git a/src/plugins/data_views/public/data_views/data_views_api_client.test.ts b/src/plugins/data_views/public/data_views/data_views_api_client.test.ts index 90a208650a965..f36776153ee3a 100644 --- a/src/plugins/data_views/public/data_views/data_views_api_client.test.ts +++ b/src/plugins/data_views/public/data_views/data_views_api_client.test.ts @@ -6,6 +6,7 @@ * Side Public License, v 1. */ +import type { HttpSetup } from '@kbn/core/public'; import { http } from './data_views_api_client.test.mock'; import { DataViewsApiClient } from './data_views_api_client'; import { FIELDS_FOR_WILDCARD_PATH as expectedPath } from '../../common/constants'; @@ -16,7 +17,7 @@ describe('IndexPatternsApiClient', () => { beforeEach(() => { fetchSpy = jest.spyOn(http, 'fetch').mockImplementation(() => Promise.resolve({})); - indexPatternsApiClient = new DataViewsApiClient(http); + indexPatternsApiClient = new DataViewsApiClient(http as HttpSetup); }); test('uses the right URI to fetch fields for wildcard', async function () { diff --git a/src/plugins/data_views/public/data_views/data_views_api_client.ts b/src/plugins/data_views/public/data_views/data_views_api_client.ts index bb53c68eafaa7..ca5782736e3cd 100644 --- a/src/plugins/data_views/public/data_views/data_views_api_client.ts +++ b/src/plugins/data_views/public/data_views/data_views_api_client.ts @@ -60,6 +60,7 @@ export class DataViewsApiClient implements IDataViewsApiClient { indexFilter, includeUnmapped, fields, + allowHidden, } = options; return this._request( FIELDS_FOR_WILDCARD_PATH, @@ -71,6 +72,7 @@ export class DataViewsApiClient implements IDataViewsApiClient { allow_no_index: allowNoIndex, include_unmapped: includeUnmapped, fields, + allow_hidden: allowHidden, }, indexFilter ? JSON.stringify({ index_filter: indexFilter }) : undefined ).then((response) => { diff --git a/src/plugins/data_views/server/content_management/data_views_storage.ts b/src/plugins/data_views/server/content_management/data_views_storage.ts index 35a9151f3f69e..bb01064d59956 100644 --- a/src/plugins/data_views/server/content_management/data_views_storage.ts +++ b/src/plugins/data_views/server/content_management/data_views_storage.ts @@ -37,6 +37,7 @@ export class DataViewsStorage extends SOContentStorage { 'runtimeFieldMap', 'allowNoIndex', 'name', + 'allowHidden', ], mSearchAdditionalSearchFields: ['name'], logger, diff --git a/src/plugins/data_views/server/fetcher/index_patterns_fetcher.ts b/src/plugins/data_views/server/fetcher/index_patterns_fetcher.ts index 82f07bd7f489a..aca312c8ea64d 100644 --- a/src/plugins/data_views/server/fetcher/index_patterns_fetcher.ts +++ b/src/plugins/data_views/server/fetcher/index_patterns_fetcher.ts @@ -71,12 +71,23 @@ export class IndexPatternsFetcher { rollupIndex?: string; indexFilter?: QueryDslQueryContainer; fields?: string[]; + allowHidden?: boolean; }): Promise<{ fields: FieldDescriptor[]; indices: string[] }> { - const { pattern, metaFields = [], fieldCapsOptions, type, rollupIndex, indexFilter } = options; + const { + pattern, + metaFields = [], + fieldCapsOptions, + type, + rollupIndex, + indexFilter, + allowHidden, + } = options; const allowNoIndices = fieldCapsOptions ? fieldCapsOptions.allow_no_indices : this.allowNoIndices; + const expandWildcards = allowHidden ? 'all' : 'open'; + const fieldCapsResponse = await getFieldCapabilities({ callCluster: this.elasticsearchClient, indices: pattern, @@ -87,6 +98,7 @@ export class IndexPatternsFetcher { }, indexFilter, fields: options.fields || ['*'], + expandWildcards, }); if (this.rollupsEnabled && type === 'rollup' && rollupIndex) { diff --git a/src/plugins/data_views/server/fetcher/lib/es_api.ts b/src/plugins/data_views/server/fetcher/lib/es_api.ts index 988e4a4ec28c8..62ad89a87f50b 100644 --- a/src/plugins/data_views/server/fetcher/lib/es_api.ts +++ b/src/plugins/data_views/server/fetcher/lib/es_api.ts @@ -7,6 +7,7 @@ */ import { ElasticsearchClient } from '@kbn/core/server'; +import { ExpandWildcard } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { QueryDslQueryContainer } from '../../../common/types'; import { convertEsError } from './errors'; @@ -45,6 +46,7 @@ interface FieldCapsApiParams { fieldCapsOptions?: { allow_no_indices: boolean; include_unmapped?: boolean }; indexFilter?: QueryDslQueryContainer; fields?: string[]; + expandWildcards?: ExpandWildcard; } /** @@ -69,6 +71,7 @@ export async function callFieldCapsApi(params: FieldCapsApiParams) { include_unmapped: false, }, fields = ['*'], + expandWildcards, } = params; try { return await callCluster.fieldCaps( @@ -77,6 +80,7 @@ export async function callFieldCapsApi(params: FieldCapsApiParams) { fields, ignore_unavailable: true, index_filter: indexFilter, + expand_wildcards: expandWildcards, ...fieldCapsOptions, }, { meta: true } diff --git a/src/plugins/data_views/server/fetcher/lib/field_capabilities/field_capabilities.test.js b/src/plugins/data_views/server/fetcher/lib/field_capabilities/field_capabilities.test.js index 1b3be374bbd7c..8ea934e9f703e 100644 --- a/src/plugins/data_views/server/fetcher/lib/field_capabilities/field_capabilities.test.js +++ b/src/plugins/data_views/server/fetcher/lib/field_capabilities/field_capabilities.test.js @@ -34,6 +34,7 @@ describe('index_patterns/field_capabilities/field_capabilities', () => { const fillUndefinedParams = (args) => ({ callCluster: undefined, indices: undefined, + expandWildcards: undefined, fieldCapsOptions: undefined, indexFilter: undefined, fields: undefined, diff --git a/src/plugins/data_views/server/fetcher/lib/field_capabilities/field_capabilities.ts b/src/plugins/data_views/server/fetcher/lib/field_capabilities/field_capabilities.ts index 73e550ebd68ce..fdf3f1afe7c44 100644 --- a/src/plugins/data_views/server/fetcher/lib/field_capabilities/field_capabilities.ts +++ b/src/plugins/data_views/server/fetcher/lib/field_capabilities/field_capabilities.ts @@ -8,6 +8,7 @@ import { defaults, keyBy, sortBy } from 'lodash'; +import { ExpandWildcard } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { ElasticsearchClient } from '@kbn/core/server'; import { callFieldCapsApi } from '../es_api'; import { readFieldCapsResponse } from './field_caps_response'; @@ -22,6 +23,7 @@ interface FieldCapabilitiesParams { fieldCapsOptions?: { allow_no_indices: boolean; include_unmapped?: boolean }; indexFilter?: QueryDslQueryContainer; fields?: string[]; + expandWildcards?: ExpandWildcard; } /** @@ -42,6 +44,7 @@ export async function getFieldCapabilities(params: FieldCapabilitiesParams) { indexFilter, metaFields = [], fields, + expandWildcards, } = params; const esFieldCaps = await callFieldCapsApi({ callCluster, @@ -49,6 +52,7 @@ export async function getFieldCapabilities(params: FieldCapabilitiesParams) { fieldCapsOptions, indexFilter, fields, + expandWildcards, }); const fieldCapsArr = readFieldCapsResponse(esFieldCaps.body); const fieldsFromFieldCapsByName = keyBy(fieldCapsArr, 'name'); diff --git a/src/plugins/data_views/server/index.ts b/src/plugins/data_views/server/index.ts index a489feabbf935..eba0a83a8df49 100644 --- a/src/plugins/data_views/server/index.ts +++ b/src/plugins/data_views/server/index.ts @@ -19,7 +19,7 @@ export type { } from './types'; import { PluginInitializerContext } from '@kbn/core/server'; -import { DataViewsServerPlugin } from './plugin'; +import type { DataViewsServerPlugin } from './plugin'; import { DataViewsServerPluginSetup, DataViewsServerPluginStart } from './types'; export type { dataViewsServiceFactory } from './data_views_service_factory'; @@ -28,7 +28,8 @@ export type { dataViewsServiceFactory } from './data_views_service_factory'; * @public */ -export function plugin(initializerContext: PluginInitializerContext) { +export async function plugin(initializerContext: PluginInitializerContext) { + const { DataViewsServerPlugin } = await import('./plugin'); return new DataViewsServerPlugin(initializerContext); } @@ -36,7 +37,7 @@ export type { DataViewsServerPluginSetup as PluginSetup, DataViewsServerPluginStart as PluginStart, }; -export { DataViewsServerPlugin as Plugin }; +export type { DataViewsServerPlugin as Plugin }; const configSchema = schema.object({ scriptedFieldsEnabled: schema.conditional( diff --git a/src/plugins/data_views/server/rest_api_routes/internal/fields_for.ts b/src/plugins/data_views/server/rest_api_routes/internal/fields_for.ts index 15d761935c0a7..7d39b41d5caee 100644 --- a/src/plugins/data_views/server/rest_api_routes/internal/fields_for.ts +++ b/src/plugins/data_views/server/rest_api_routes/internal/fields_for.ts @@ -50,6 +50,7 @@ interface IQuery { allow_no_index?: boolean; include_unmapped?: boolean; fields?: string[]; + allow_hidden?: boolean; } const querySchema = schema.object({ @@ -62,6 +63,7 @@ const querySchema = schema.object({ allow_no_index: schema.maybe(schema.boolean()), include_unmapped: schema.maybe(schema.boolean()), fields: schema.maybe(schema.oneOf([schema.string(), schema.arrayOf(schema.string())])), + allow_hidden: schema.maybe(schema.boolean()), }); const fieldSubTypeSchema = schema.object({ @@ -122,6 +124,7 @@ const handler: (isRollupsEnabled: () => boolean) => RequestHandler<{}, IQuery, I rollup_index: rollupIndex, allow_no_index: allowNoIndex, include_unmapped: includeUnmapped, + allow_hidden: allowHidden, } = request.query; // not available to get request @@ -147,6 +150,7 @@ const handler: (isRollupsEnabled: () => boolean) => RequestHandler<{}, IQuery, I includeUnmapped, }, indexFilter, + allowHidden, ...(parsedFields.length > 0 ? { fields: parsedFields } : {}), }); diff --git a/src/plugins/data_views/server/rest_api_routes/route_types.ts b/src/plugins/data_views/server/rest_api_routes/route_types.ts index 106817973e8a2..f7786c31faaa6 100644 --- a/src/plugins/data_views/server/rest_api_routes/route_types.ts +++ b/src/plugins/data_views/server/rest_api_routes/route_types.ts @@ -121,6 +121,7 @@ export type DataViewSpecRestResponse = { allowNoIndex?: boolean; namespaces?: string[]; name?: string; + allowHidden?: boolean; }; export interface DataViewListItemRestResponse { diff --git a/src/plugins/data_views/server/rest_api_routes/schema.ts b/src/plugins/data_views/server/rest_api_routes/schema.ts index 6db8c5138a52b..d39d6dbb10b54 100644 --- a/src/plugins/data_views/server/rest_api_routes/schema.ts +++ b/src/plugins/data_views/server/rest_api_routes/schema.ts @@ -46,6 +46,7 @@ export const dataViewSpecSchema = schema.object({ runtimeFieldMap: schema.maybe(schema.recordOf(schema.string(), runtimeFieldSchema)), name: schema.maybe(schema.string()), namespaces: schema.maybe(schema.arrayOf(schema.string())), + allowHidden: schema.maybe(schema.boolean()), }); export const dataViewsRuntimeResponseSchema = schema.object({ diff --git a/src/plugins/dev_tools/server/index.ts b/src/plugins/dev_tools/server/index.ts index ca7d3a5b0eb32..0b572bdacf98c 100644 --- a/src/plugins/dev_tools/server/index.ts +++ b/src/plugins/dev_tools/server/index.ts @@ -7,9 +7,10 @@ */ import { PluginInitializerContext } from '@kbn/core/server'; -import { DevToolsServerPlugin } from './plugin'; export { config } from './config'; -export const plugin = (initContext: PluginInitializerContext) => - new DevToolsServerPlugin(initContext); +export const plugin = async (initContext: PluginInitializerContext) => { + const { DevToolsServerPlugin } = await import('./plugin'); + return new DevToolsServerPlugin(initContext); +}; diff --git a/src/plugins/discover/public/__mocks__/data_view_complex.ts b/src/plugins/discover/public/__mocks__/data_view_complex.ts index 03161a0df4e3f..05051f48b155c 100644 --- a/src/plugins/discover/public/__mocks__/data_view_complex.ts +++ b/src/plugins/discover/public/__mocks__/data_view_complex.ts @@ -426,3 +426,18 @@ export const dataViewAdHoc = { }), isPersisted: () => false, } as DataView; + +export const dataViewWithDefaultColumnMock = buildDataViewMock({ + name: 'data-view-with-user-default-column', + fields: [ + ...fields, + { + name: 'default_column', + type: 'date', + scripted: false, + searchable: true, + aggregatable: true, + }, + ] as DataView['fields'], + timeFieldName: '@timestamp', +}); diff --git a/src/plugins/discover/public/application/context/context_app_content.tsx b/src/plugins/discover/public/application/context/context_app_content.tsx index 098f789be1a6f..84d2126f15495 100644 --- a/src/plugins/discover/public/application/context/context_app_content.tsx +++ b/src/plugins/discover/public/application/context/context_app_content.tsx @@ -151,7 +151,7 @@ export function ContextAppContent({ return ( - {interceptedWarnings.length && ( + {Boolean(interceptedWarnings.length) && ( <> diff --git a/src/plugins/discover/public/application/main/hooks/utils/change_data_view.test.ts b/src/plugins/discover/public/application/main/hooks/utils/change_data_view.test.ts index 37a503716af0e..a0266b65ed01d 100644 --- a/src/plugins/discover/public/application/main/hooks/utils/change_data_view.test.ts +++ b/src/plugins/discover/public/application/main/hooks/utils/change_data_view.test.ts @@ -6,11 +6,14 @@ * Side Public License, v 1. */ +import { + dataViewComplexMock, + dataViewWithDefaultColumnMock, +} from '../../../../__mocks__/data_view_complex'; import { changeDataView } from './change_data_view'; import { savedSearchMock } from '../../../../__mocks__/saved_search'; import { discoverServiceMock } from '../../../../__mocks__/services'; import type { DataView } from '@kbn/data-views-plugin/common'; -import { dataViewComplexMock } from '../../../../__mocks__/data_view_complex'; import { getDiscoverStateMock } from '../../../../__mocks__/discover_state.mock'; const setupTestParams = (dataView: DataView | undefined) => { @@ -27,11 +30,21 @@ const setupTestParams = (dataView: DataView | undefined) => { }; describe('changeDataView', () => { + it('should set the right app state when a valid data view (which includes the preconfigured default column) to switch to is given', async () => { + const params = setupTestParams(dataViewWithDefaultColumnMock); + await changeDataView(dataViewWithDefaultColumnMock.id!, params); + expect(params.appState.update).toHaveBeenCalledWith({ + columns: ['default_column'], // default_column would be added as dataViewWithDefaultColumn has it as a mapped field + index: 'data-view-with-user-default-column-id', + sort: [['@timestamp', 'desc']], + }); + }); + it('should set the right app state when a valid data view to switch to is given', async () => { - const params = setupTestParams(dataViewComplexMock as DataView); - await changeDataView('data-view-with-various-field-types', params); + const params = setupTestParams(dataViewComplexMock); + await changeDataView(dataViewComplexMock.id!, params); expect(params.appState.update).toHaveBeenCalledWith({ - columns: ['default_column'], + columns: [], // default_column would not be added as dataViewComplexMock does not have it as a mapped field index: 'data-view-with-various-field-types-id', sort: [['data', 'desc']], }); diff --git a/src/plugins/discover/public/application/main/hooks/utils/change_data_view.ts b/src/plugins/discover/public/application/main/hooks/utils/change_data_view.ts index db7a4b0c00bbe..7218ea76b2ac6 100644 --- a/src/plugins/discover/public/application/main/hooks/utils/change_data_view.ts +++ b/src/plugins/discover/public/application/main/hooks/utils/change_data_view.ts @@ -8,7 +8,11 @@ import { SortOrder } from '@kbn/saved-search-plugin/public'; import { DataView } from '@kbn/data-views-plugin/common'; -import { MODIFY_COLUMNS_ON_SWITCH, SORT_DEFAULT_ORDER_SETTING } from '@kbn/discover-utils'; +import { + MODIFY_COLUMNS_ON_SWITCH, + SORT_DEFAULT_ORDER_SETTING, + DEFAULT_COLUMNS_SETTING, +} from '@kbn/discover-utils'; import { DiscoverInternalStateContainer } from '../../services/discover_internal_state_container'; import { DiscoverAppStateContainer } from '../../services/discover_app_state_container'; import { addLog } from '../../../../utils/add_log'; @@ -46,6 +50,7 @@ export async function changeDataView( const nextAppState = getDataViewAppState( dataView, nextDataView, + uiSettings.get(DEFAULT_COLUMNS_SETTING, []), state.columns || [], (state.sort || []) as SortOrder[], uiSettings.get(MODIFY_COLUMNS_ON_SWITCH), diff --git a/src/plugins/discover/public/application/main/services/discover_state.test.ts b/src/plugins/discover/public/application/main/services/discover_state.test.ts index dd2bc17bd891a..c946ac70bbe62 100644 --- a/src/plugins/discover/public/application/main/services/discover_state.test.ts +++ b/src/plugins/discover/public/application/main/services/discover_state.test.ts @@ -704,7 +704,7 @@ describe('Test discover state actions', () => { await state.actions.onChangeDataView(dataViewComplexMock.id!); await new Promise(process.nextTick); expect(getCurrentUrl()).toMatchInlineSnapshot( - `"/#?_g=(refreshInterval:(pause:!t,value:1000),time:(from:now-15d,to:now))&_a=(columns:!(default_column),index:data-view-with-various-field-types-id,interval:auto,sort:!(!(data,desc)))"` + `"/#?_g=(refreshInterval:(pause:!t,value:1000),time:(from:now-15d,to:now))&_a=(columns:!(),index:data-view-with-various-field-types-id,interval:auto,sort:!(!(data,desc)))"` ); await waitFor(() => { expect(state.dataState.fetch).toHaveBeenCalledTimes(1); diff --git a/src/plugins/discover/public/application/main/utils/get_switch_data_view_app_state.test.ts b/src/plugins/discover/public/application/main/utils/get_switch_data_view_app_state.test.ts index cf987c8c71090..e265a90ab291d 100644 --- a/src/plugins/discover/public/application/main/utils/get_switch_data_view_app_state.test.ts +++ b/src/plugins/discover/public/application/main/utils/get_switch_data_view_app_state.test.ts @@ -9,6 +9,8 @@ import { getDataViewAppState } from './get_switch_data_view_app_state'; import { DataView } from '@kbn/data-views-plugin/public'; +const emptyDefaultColumns: string[] = []; + /** * Helper function returning an data view */ @@ -36,23 +38,36 @@ const getDataView = (id: string, timeFieldName: string, fields: string[]) => { }; const currentDataView = getDataView('curr', '', ['category', 'name']); -const nextDataView = getDataView('next', '', ['category']); +const nextDataView = getDataView('next', '', ['category', 'user_default_column']); describe('Discover getDataViewAppState', () => { test('removing fields that are not part of the next data view, keeping unknown fields ', async () => { const result = getDataViewAppState( currentDataView, nextDataView, + emptyDefaultColumns, ['category', 'name', 'unknown'], [['category', 'desc']] ); expect(result.columns).toEqual(['category', 'unknown']); expect(result.sort).toEqual([['category', 'desc']]); }); + test('removing fields that are not part of the next data view and adding default columns', async () => { + const result = getDataViewAppState( + currentDataView, + nextDataView, + ['user_default_column', 'user_unknown_default_column'], + ['category', 'name', 'user_default_column'], + [['category', 'desc']] + ); + expect(result.columns).toEqual(['category', 'user_default_column']); + expect(result.sort).toEqual([['category', 'desc']]); + }); test('removing sorted by fields that are not part of the next data view', async () => { const result = getDataViewAppState( currentDataView, nextDataView, + emptyDefaultColumns, ['name'], [ ['category', 'desc'], @@ -66,6 +81,7 @@ describe('Discover getDataViewAppState', () => { const result = getDataViewAppState( currentDataView, nextDataView, + emptyDefaultColumns, ['name'], [ ['category', 'desc'], @@ -80,7 +96,13 @@ describe('Discover getDataViewAppState', () => { const current = getDataView('a', 'timeFieldA', ['timeFieldA']); const next = getDataView('b', 'timeFieldB', ['timeFieldB']); - const result = getDataViewAppState(current, next, [], [['timeFieldA', 'desc']]); + const result = getDataViewAppState( + current, + next, + emptyDefaultColumns, + [], + [['timeFieldA', 'desc']] + ); expect(result.columns).toEqual([]); expect(result.sort).toEqual([['timeFieldB', 'desc']]); }); @@ -89,7 +111,13 @@ describe('Discover getDataViewAppState', () => { const current = getDataView('a', 'timeFieldA', ['timeFieldA']); const next = getDataView('b', '', ['timeFieldA']); - const result = getDataViewAppState(current, next, [], [['timeFieldA', 'desc']]); + const result = getDataViewAppState( + current, + next, + emptyDefaultColumns, + [], + [['timeFieldA', 'desc']] + ); expect(result.columns).toEqual([]); expect(result.sort).toEqual([]); }); @@ -97,7 +125,7 @@ describe('Discover getDataViewAppState', () => { const current = getDataView('b', '', ['timeFieldA']); const next = getDataView('a', 'timeFieldA', ['timeFieldA']); - const result = getDataViewAppState(current, next, [], []); + const result = getDataViewAppState(current, next, emptyDefaultColumns, [], []); expect(result.columns).toEqual([]); expect(result.sort).toEqual([['timeFieldA', 'desc']]); }); @@ -105,8 +133,16 @@ describe('Discover getDataViewAppState', () => { const current = getDataView('timebased', 'timefield', ['timefield']); const next = getDataView('timebased2', 'timefield2', ['timefield', 'timefield2']); - const result = getDataViewAppState(current, next, [], [['timefield', 'desc']]); + const result = getDataViewAppState( + current, + next, + emptyDefaultColumns, + [], + [['timefield', 'desc']] + ); expect(result.columns).toEqual([]); expect(result.sort).toEqual([['timefield2', 'desc']]); }); + + // TODO: add tests }); diff --git a/src/plugins/discover/public/application/main/utils/get_switch_data_view_app_state.ts b/src/plugins/discover/public/application/main/utils/get_switch_data_view_app_state.ts index 064fe36d974ec..9597aa8537425 100644 --- a/src/plugins/discover/public/application/main/utils/get_switch_data_view_app_state.ts +++ b/src/plugins/discover/public/application/main/utils/get_switch_data_view_app_state.ts @@ -5,6 +5,7 @@ * in compliance with, at your election, the Elastic License 2.0 or the Server * Side Public License, v 1. */ +import { uniq } from 'lodash'; import { isOfAggregateQueryType, Query, AggregateQuery } from '@kbn/es-query'; import type { DataView } from '@kbn/data-views-plugin/public'; import type { SortOrder } from '@kbn/saved-search-plugin/public'; @@ -17,20 +18,25 @@ import { getSortArray } from '../../../utils/sorting'; export function getDataViewAppState( currentDataView: DataView, nextDataView: DataView, + defaultColumns: string[], currentColumns: string[], currentSort: SortOrder[], modifyColumns: boolean = true, sortDirection: string = 'desc', query?: Query | AggregateQuery ) { - const nextColumns = modifyColumns - ? currentColumns.filter( - (column) => - nextDataView.fields.getByName(column) || !currentDataView.fields.getByName(column) - ) - : currentColumns; + let columns = currentColumns || []; + + if (modifyColumns) { + const currentUnknownColumns = columns.filter( + (column) => !currentDataView.fields.getByName(column) && !defaultColumns.includes(column) + ); + const currentColumnsRefreshed = uniq([...columns, ...defaultColumns]); + columns = currentColumnsRefreshed.filter( + (column) => nextDataView.fields.getByName(column) || currentUnknownColumns.includes(column) + ); + } - let columns = nextColumns.length ? nextColumns : []; if (query && isOfAggregateQueryType(query)) { columns = []; } diff --git a/src/plugins/discover/public/components/common/error_callout.tsx b/src/plugins/discover/public/components/common/error_callout.tsx index 1b3e8f02f39a3..9b6aa341d5fdc 100644 --- a/src/plugins/discover/public/components/common/error_callout.tsx +++ b/src/plugins/discover/public/components/common/error_callout.tsx @@ -32,6 +32,7 @@ export const ErrorCallout = ({ title, error }: Props) => { iconType="error" color="danger" title={

{overrideDisplay?.title ?? title}

} + actions={overrideDisplay?.actions ?? []} body={
; + +export const config: PluginConfigDescriptor = { + schema: configSchema, +}; diff --git a/src/plugins/discover/server/index.ts b/src/plugins/discover/server/index.ts index f899060f0304c..4ec924a258590 100644 --- a/src/plugins/discover/server/index.ts +++ b/src/plugins/discover/server/index.ts @@ -6,10 +6,9 @@ * Side Public License, v 1. */ -import { KibanaRequest } from '@kbn/core/server'; +import { KibanaRequest, PluginInitializerContext } from '@kbn/core/server'; import { DataPluginStart } from '@kbn/data-plugin/server/plugin'; import { ColumnsFromLocatorFn, SearchSourceFromLocatorFn, TitleFromLocatorFn } from './locator'; -import { DiscoverServerPlugin } from './plugin'; export interface DiscoverServerPluginStartDeps { data: DataPluginStart; @@ -29,4 +28,9 @@ export interface DiscoverServerPluginStart { locator: DiscoverServerPluginLocatorService; } -export const plugin = () => new DiscoverServerPlugin(); +export { config } from './config'; + +export const plugin = async (context: PluginInitializerContext) => { + const { DiscoverServerPlugin } = await import('./plugin'); + return new DiscoverServerPlugin(context); +}; diff --git a/src/plugins/discover/server/plugin.ts b/src/plugins/discover/server/plugin.ts index b12833edf67a1..dc7761b2ba20d 100644 --- a/src/plugins/discover/server/plugin.ts +++ b/src/plugins/discover/server/plugin.ts @@ -12,6 +12,7 @@ import type { EmbeddableSetup } from '@kbn/embeddable-plugin/server'; import type { HomeServerPluginSetup } from '@kbn/home-plugin/server'; import { setStateToKbnUrl } from '@kbn/kibana-utils-plugin/common'; import type { SharePluginSetup } from '@kbn/share-plugin/server'; +import { PluginInitializerContext } from '@kbn/core/server'; import type { DiscoverServerPluginStart, DiscoverServerPluginStartDeps } from '.'; import { DiscoverAppLocatorDefinition } from '../common/locator'; import { capabilitiesProvider } from './capabilities_provider'; @@ -19,10 +20,17 @@ import { createSearchEmbeddableFactory } from './embeddable'; import { initializeLocatorServices } from './locator'; import { registerSampleData } from './sample_data'; import { getUiSettings } from './ui_settings'; +import { ConfigSchema } from './config'; export class DiscoverServerPlugin implements Plugin { + private readonly config: ConfigSchema; + + constructor(initializerContext: PluginInitializerContext) { + this.config = initializerContext.config.get(); + } + public setup( core: CoreSetup, plugins: { @@ -33,7 +41,7 @@ export class DiscoverServerPlugin } ) { core.capabilities.registerProvider(capabilitiesProvider); - core.uiSettings.register(getUiSettings(core.docLinks)); + core.uiSettings.register(getUiSettings(core.docLinks, this.config.enableUiSettingsValidations)); if (plugins.home) { registerSampleData(plugins.home.sampleData); diff --git a/src/plugins/discover/server/ui_settings.ts b/src/plugins/discover/server/ui_settings.ts index d6bbbd0eed9f0..806ae826bf3ab 100644 --- a/src/plugins/discover/server/ui_settings.ts +++ b/src/plugins/discover/server/ui_settings.ts @@ -38,8 +38,12 @@ const technicalPreviewLabel = i18n.translate('discover.advancedSettings.technica defaultMessage: 'technical preview', }); -export const getUiSettings: (docLinks: DocLinksServiceSetup) => Record = ( - docLinks: DocLinksServiceSetup +export const getUiSettings: ( + docLinks: DocLinksServiceSetup, + enableValidations: boolean +) => Record = ( + docLinks: DocLinksServiceSetup, + enableValidations: boolean ) => ({ [DEFAULT_COLUMNS_SETTING]: { name: i18n.translate('discover.advancedSettings.defaultColumnsTitle', { @@ -51,7 +55,9 @@ export const getUiSettings: (docLinks: DocLinksServiceSetup) => Record + {label} + + ); + } + useEffect(() => { const subscription = merge(embeddable.getInput$(), embeddable.getOutput$()) .pipe( @@ -65,25 +81,21 @@ export function EmbeddablePanelError({ return ( - - + overrideDisplay?.body ?? ( + + + + ) } data-test-subj="embeddableStackError" iconType="warning" iconColor="danger" layout="vertical" - actions={ - isEditable && ( - - {label} - - ) - } + actions={actions} /> ); } diff --git a/src/plugins/embeddable/public/plugin.tsx b/src/plugins/embeddable/public/plugin.tsx index c56e4e381ce5c..d7af8f68817ea 100644 --- a/src/plugins/embeddable/public/plugin.tsx +++ b/src/plugins/embeddable/public/plugin.tsx @@ -54,7 +54,6 @@ import { getTelemetryFunction, } from '../common/lib'; import { getAllMigrations } from '../common/lib/get_all_migrations'; -import { setTheme } from './services'; import { setKibanaServices } from './kibana_services'; import { CustomTimeRangeBadge, EditPanelAction } from './embeddable_panel/panel_actions'; @@ -120,7 +119,6 @@ export class EmbeddablePublicPlugin implements Plugin new EmbeddableServerPlugin(); +export const plugin = async () => { + const { EmbeddableServerPlugin } = await import('./plugin'); + return new EmbeddableServerPlugin(); +}; diff --git a/src/plugins/es_ui_shared/server/index.ts b/src/plugins/es_ui_shared/server/index.ts index 6fe8c913875a0..5e5d1010c3b24 100644 --- a/src/plugins/es_ui_shared/server/index.ts +++ b/src/plugins/es_ui_shared/server/index.ts @@ -9,7 +9,7 @@ export { handleEsError, parseEsError } from './errors'; /** dummy plugin*/ -export function plugin() { +export async function plugin() { return new (class EsUiSharedPlugin { setup() {} start() {} diff --git a/src/plugins/event_annotation/server/index.ts b/src/plugins/event_annotation/server/index.ts index 84fecda35d4f1..7952fb67d3f88 100644 --- a/src/plugins/event_annotation/server/index.ts +++ b/src/plugins/event_annotation/server/index.ts @@ -7,7 +7,8 @@ */ import { PluginInitializerContext } from '@kbn/core-plugins-server'; -import { EventAnnotationServerPlugin } from './plugin'; -export const plugin = (initializerContext: PluginInitializerContext) => - new EventAnnotationServerPlugin(initializerContext); +export const plugin = async (initializerContext: PluginInitializerContext) => { + const { EventAnnotationServerPlugin } = await import('./plugin'); + return new EventAnnotationServerPlugin(initializerContext); +}; diff --git a/src/plugins/expression_image/server/index.ts b/src/plugins/expression_image/server/index.ts index a4c6ee888d086..4f0087b6f262d 100755 --- a/src/plugins/expression_image/server/index.ts +++ b/src/plugins/expression_image/server/index.ts @@ -6,10 +6,9 @@ * Side Public License, v 1. */ -import { ExpressionImagePlugin } from './plugin'; - export type { ExpressionImagePluginSetup, ExpressionImagePluginStart } from './plugin'; -export function plugin() { +export async function plugin() { + const { ExpressionImagePlugin } = await import('./plugin'); return new ExpressionImagePlugin(); } diff --git a/src/plugins/expression_metric/server/index.ts b/src/plugins/expression_metric/server/index.ts index 0caafe1b69262..f9eb950b9ceae 100755 --- a/src/plugins/expression_metric/server/index.ts +++ b/src/plugins/expression_metric/server/index.ts @@ -6,10 +6,9 @@ * Side Public License, v 1. */ -import { ExpressionMetricPlugin } from './plugin'; - export type { ExpressionMetricPluginSetup, ExpressionMetricPluginStart } from './plugin'; -export function plugin() { +export async function plugin() { + const { ExpressionMetricPlugin } = await import('./plugin'); return new ExpressionMetricPlugin(); } diff --git a/src/plugins/expression_repeat_image/server/index.ts b/src/plugins/expression_repeat_image/server/index.ts index 07d0df9f78e05..0bc2ce114c5a6 100755 --- a/src/plugins/expression_repeat_image/server/index.ts +++ b/src/plugins/expression_repeat_image/server/index.ts @@ -6,10 +6,9 @@ * Side Public License, v 1. */ -import { ExpressionRepeatImagePlugin } from './plugin'; - export type { ExpressionRepeatImagePluginSetup, ExpressionRepeatImagePluginStart } from './plugin'; -export function plugin() { +export async function plugin() { + const { ExpressionRepeatImagePlugin } = await import('./plugin'); return new ExpressionRepeatImagePlugin(); } diff --git a/src/plugins/expression_reveal_image/server/index.ts b/src/plugins/expression_reveal_image/server/index.ts index b86c356974321..5675e194669d0 100644 --- a/src/plugins/expression_reveal_image/server/index.ts +++ b/src/plugins/expression_reveal_image/server/index.ts @@ -6,10 +6,9 @@ * Side Public License, v 1. */ -import { ExpressionRevealImagePlugin } from './plugin'; - export type { ExpressionRevealImagePluginSetup, ExpressionRevealImagePluginStart } from './plugin'; -export function plugin() { +export async function plugin() { + const { ExpressionRevealImagePlugin } = await import('./plugin'); return new ExpressionRevealImagePlugin(); } diff --git a/src/plugins/expression_shape/server/index.ts b/src/plugins/expression_shape/server/index.ts index 79da7a954c550..8fd3ea9d48fe9 100644 --- a/src/plugins/expression_shape/server/index.ts +++ b/src/plugins/expression_shape/server/index.ts @@ -6,10 +6,9 @@ * Side Public License, v 1. */ -import { ExpressionShapePlugin } from './plugin'; - export type { ExpressionShapePluginSetup, ExpressionShapePluginStart } from './plugin'; -export function plugin() { +export async function plugin() { + const { ExpressionShapePlugin } = await import('./plugin'); return new ExpressionShapePlugin(); } diff --git a/src/plugins/expressions/server/index.ts b/src/plugins/expressions/server/index.ts index 2e087d33c7aa5..b0e6cdc15f81a 100644 --- a/src/plugins/expressions/server/index.ts +++ b/src/plugins/expressions/server/index.ts @@ -7,13 +7,14 @@ */ import { PluginInitializerContext } from '@kbn/core/server'; -import { ExpressionsServerPlugin } from './plugin'; +import type { ExpressionsServerPlugin } from './plugin'; export type { ExpressionsServerSetup, ExpressionsServerStart } from './plugin'; // Kibana Platform. export { ExpressionsServerPlugin as Plugin }; -export function plugin(initializerContext: PluginInitializerContext) { +export async function plugin(initializerContext: PluginInitializerContext) { + const { ExpressionsServerPlugin } = await import('./plugin'); return new ExpressionsServerPlugin(initializerContext); } diff --git a/src/plugins/expressions/server/mocks.ts b/src/plugins/expressions/server/mocks.ts index df5232ab5faf5..db6348d1d3fe9 100644 --- a/src/plugins/expressions/server/mocks.ts +++ b/src/plugins/expressions/server/mocks.ts @@ -41,7 +41,7 @@ const createPlugin = async () => { const pluginInitializerContext = coreMock.createPluginInitializerContext(); const coreSetup = coreMock.createSetup(); const coreStart = coreMock.createStart(); - const plugin = pluginInitializer(pluginInitializerContext); + const plugin = await pluginInitializer(pluginInitializerContext); const setup = await plugin.setup(coreSetup); return { diff --git a/src/plugins/field_formats/server/index.ts b/src/plugins/field_formats/server/index.ts index bcc94c38dd0d8..b268665b0fa3f 100755 --- a/src/plugins/field_formats/server/index.ts +++ b/src/plugins/field_formats/server/index.ts @@ -7,10 +7,10 @@ */ import { PluginInitializerContext } from '@kbn/core/server'; -import { FieldFormatsPlugin } from './plugin'; export { DateFormat, DateNanosFormat } from './lib/converters'; -export function plugin(initializerContext: PluginInitializerContext) { +export async function plugin(initializerContext: PluginInitializerContext) { + const { FieldFormatsPlugin } = await import('./plugin'); return new FieldFormatsPlugin(initializerContext); } diff --git a/src/plugins/files/server/index.ts b/src/plugins/files/server/index.ts index 181124fc27496..f02a0164b1f69 100755 --- a/src/plugins/files/server/index.ts +++ b/src/plugins/files/server/index.ts @@ -7,7 +7,6 @@ */ import type { PluginInitializerContext } from '@kbn/core/server'; -import { FilesPlugin } from './plugin'; export type { FileClient, @@ -44,6 +43,7 @@ export type { } from './file_service'; export type { FileServiceFactory } from './file_service/file_service_factory'; -export function plugin(initializerContext: PluginInitializerContext) { +export async function plugin(initializerContext: PluginInitializerContext) { + const { FilesPlugin } = await import('./plugin'); return new FilesPlugin(initializerContext); } diff --git a/src/plugins/ftr_apis/server/index.ts b/src/plugins/ftr_apis/server/index.ts index 5c33f6c4a067a..dfd8f08061931 100644 --- a/src/plugins/ftr_apis/server/index.ts +++ b/src/plugins/ftr_apis/server/index.ts @@ -7,9 +7,9 @@ */ import type { PluginInitializerContext } from '@kbn/core/server'; -import { FtrApisPlugin } from './plugin'; -export function plugin(initializerContext: PluginInitializerContext) { +export async function plugin(initializerContext: PluginInitializerContext) { + const { FtrApisPlugin } = await import('./plugin'); return new FtrApisPlugin(initializerContext); } diff --git a/src/plugins/guided_onboarding/server/index.ts b/src/plugins/guided_onboarding/server/index.ts index 823cc4daf3578..01d92ceaf4655 100755 --- a/src/plugins/guided_onboarding/server/index.ts +++ b/src/plugins/guided_onboarding/server/index.ts @@ -7,9 +7,9 @@ */ import { PluginInitializerContext } from '@kbn/core/server'; -import { GuidedOnboardingPlugin } from './plugin'; -export function plugin(initializerContext: PluginInitializerContext) { +export async function plugin(initializerContext: PluginInitializerContext) { + const { GuidedOnboardingPlugin } = await import('./plugin'); return new GuidedOnboardingPlugin(initializerContext); } diff --git a/src/plugins/home/server/index.ts b/src/plugins/home/server/index.ts index d93f864fb7af4..d1763b2833b3e 100644 --- a/src/plugins/home/server/index.ts +++ b/src/plugins/home/server/index.ts @@ -23,7 +23,6 @@ export type { ScopedTutorialContextFactory, } from './services'; import { PluginInitializerContext, PluginConfigDescriptor } from '@kbn/core/server'; -import { HomeServerPlugin } from './plugin'; import { configSchema, ConfigSchema } from '../config'; export const config: PluginConfigDescriptor = { @@ -33,6 +32,9 @@ export const config: PluginConfigDescriptor = { schema: configSchema, }; -export const plugin = (initContext: PluginInitializerContext) => new HomeServerPlugin(initContext); +export const plugin = async (initContext: PluginInitializerContext) => { + const { HomeServerPlugin } = await import('./plugin'); + return new HomeServerPlugin(initContext); +}; export { INSTRUCTION_VARIANT } from '../common/instruction_variant'; diff --git a/src/plugins/home/server/services/sample_data/data_sets/ecommerce/index.ts b/src/plugins/home/server/services/sample_data/data_sets/ecommerce/index.ts index e995510c99fee..f68036496914d 100644 --- a/src/plugins/home/server/services/sample_data/data_sets/ecommerce/index.ts +++ b/src/plugins/home/server/services/sample_data/data_sets/ecommerce/index.ts @@ -10,7 +10,7 @@ import path from 'path'; import { i18n } from '@kbn/i18n'; import { getSavedObjects } from './saved_objects'; import { fieldMappings } from './field_mappings'; -import { SampleDatasetSchema } from '../../lib/sample_dataset_registry_types'; +import { SampleDatasetProvider } from '../../lib/sample_dataset_registry_types'; const ecommerceName = i18n.translate('home.sampleData.ecommerceSpecTitle', { defaultMessage: 'Sample eCommerce orders', @@ -19,14 +19,17 @@ const ecommerceDescription = i18n.translate('home.sampleData.ecommerceSpecDescri defaultMessage: 'Sample data, visualizations, and dashboards for tracking eCommerce orders.', }); -export const ecommerceSpecProvider = function (): SampleDatasetSchema { +export const ecommerceSpecProvider: SampleDatasetProvider = ({ staticAssets }) => { return { id: 'ecommerce', name: ecommerceName, description: ecommerceDescription, - previewImagePath: '/plugins/home/assets/sample_data_resources/ecommerce/dashboard.webp', - darkPreviewImagePath: - '/plugins/home/assets/sample_data_resources/ecommerce/dashboard_dark.webp', + previewImagePath: staticAssets.getPluginAssetHref( + '/sample_data_resources/ecommerce/dashboard.webp' + ), + darkPreviewImagePath: staticAssets.getPluginAssetHref( + '/sample_data_resources/ecommerce/dashboard_dark.webp' + ), overviewDashboard: '722b74f0-b882-11e8-a6d9-e546fe2bba5f', defaultIndex: 'ff959d40-b880-11e8-a6d9-e546fe2bba5f', savedObjects: getSavedObjects(), @@ -41,6 +44,6 @@ export const ecommerceSpecProvider = function (): SampleDatasetSchema { }, ], status: 'not_installed', - iconPath: '/plugins/home/assets/sample_data_resources/ecommerce/icon.svg', + iconPath: staticAssets.getPluginAssetHref('/sample_data_resources/ecommerce/icon.svg'), }; }; diff --git a/src/plugins/home/server/services/sample_data/data_sets/flights/index.ts b/src/plugins/home/server/services/sample_data/data_sets/flights/index.ts index 691ac8334cbc3..7481f4cd50721 100644 --- a/src/plugins/home/server/services/sample_data/data_sets/flights/index.ts +++ b/src/plugins/home/server/services/sample_data/data_sets/flights/index.ts @@ -10,7 +10,7 @@ import path from 'path'; import { i18n } from '@kbn/i18n'; import { getSavedObjects } from './saved_objects'; import { fieldMappings } from './field_mappings'; -import { SampleDatasetSchema } from '../../lib/sample_dataset_registry_types'; +import { SampleDatasetProvider } from '../../lib/sample_dataset_registry_types'; const flightsName = i18n.translate('home.sampleData.flightsSpecTitle', { defaultMessage: 'Sample flight data', @@ -19,13 +19,17 @@ const flightsDescription = i18n.translate('home.sampleData.flightsSpecDescriptio defaultMessage: 'Sample data, visualizations, and dashboards for monitoring flight routes.', }); -export const flightsSpecProvider = function (): SampleDatasetSchema { +export const flightsSpecProvider: SampleDatasetProvider = ({ staticAssets }) => { return { id: 'flights', name: flightsName, description: flightsDescription, - previewImagePath: '/plugins/home/assets/sample_data_resources/flights/dashboard.webp', - darkPreviewImagePath: '/plugins/home/assets/sample_data_resources/flights/dashboard_dark.webp', + previewImagePath: staticAssets.getPluginAssetHref( + '/sample_data_resources/flights/dashboard.webp' + ), + darkPreviewImagePath: staticAssets.getPluginAssetHref( + '/sample_data_resources/flights/dashboard_dark.webp' + ), overviewDashboard: '7adfa750-4c81-11e8-b3d7-01146121b73d', defaultIndex: 'd3d7af60-4c81-11e8-b3d7-01146121b73d', savedObjects: getSavedObjects(), @@ -40,6 +44,6 @@ export const flightsSpecProvider = function (): SampleDatasetSchema { }, ], status: 'not_installed', - iconPath: '/plugins/home/assets/sample_data_resources/flights/icon.svg', + iconPath: staticAssets.getPluginAssetHref('/sample_data_resources/flights/icon.svg'), }; }; diff --git a/src/plugins/home/server/services/sample_data/data_sets/logs/index.ts b/src/plugins/home/server/services/sample_data/data_sets/logs/index.ts index 219b7ea2cc9d0..6f001e85c6151 100644 --- a/src/plugins/home/server/services/sample_data/data_sets/logs/index.ts +++ b/src/plugins/home/server/services/sample_data/data_sets/logs/index.ts @@ -10,7 +10,7 @@ import path from 'path'; import { i18n } from '@kbn/i18n'; import { getSavedObjects } from './saved_objects'; import { fieldMappings } from './field_mappings'; -import { SampleDatasetSchema } from '../../lib/sample_dataset_registry_types'; +import { SampleDatasetProvider } from '../../lib/sample_dataset_registry_types'; const logsName = i18n.translate('home.sampleData.logsSpecTitle', { defaultMessage: 'Sample web logs', @@ -20,13 +20,15 @@ const logsDescription = i18n.translate('home.sampleData.logsSpecDescription', { }); export const GLOBE_ICON_PATH = '/plugins/home/assets/sample_data_resources/logs/icon.svg'; -export const logsSpecProvider = function (): SampleDatasetSchema { +export const logsSpecProvider: SampleDatasetProvider = ({ staticAssets }) => { return { id: 'logs', name: logsName, description: logsDescription, - previewImagePath: '/plugins/home/assets/sample_data_resources/logs/dashboard.webp', - darkPreviewImagePath: '/plugins/home/assets/sample_data_resources/logs/dashboard_dark.webp', + previewImagePath: staticAssets.getPluginAssetHref('/sample_data_resources/logs/dashboard.webp'), + darkPreviewImagePath: staticAssets.getPluginAssetHref( + '/sample_data_resources/logs/dashboard_dark.webp' + ), overviewDashboard: 'edf84fe0-e1a0-11e7-b6d5-4dc382ef7f5b', defaultIndex: '90943e30-9a47-11e8-b64d-95841ca0b247', savedObjects: getSavedObjects(), @@ -42,6 +44,6 @@ export const logsSpecProvider = function (): SampleDatasetSchema { }, ], status: 'not_installed', - iconPath: GLOBE_ICON_PATH, + iconPath: staticAssets.getPluginAssetHref('/sample_data_resources/logs/icon.svg'), }; }; diff --git a/src/plugins/home/server/services/sample_data/data_sets/logs_tsdb/index.ts b/src/plugins/home/server/services/sample_data/data_sets/logs_tsdb/index.ts index bfc4ec4554191..39dc153eb2b19 100644 --- a/src/plugins/home/server/services/sample_data/data_sets/logs_tsdb/index.ts +++ b/src/plugins/home/server/services/sample_data/data_sets/logs_tsdb/index.ts @@ -10,7 +10,7 @@ import path from 'path'; import { i18n } from '@kbn/i18n'; import { getSavedObjects } from './saved_objects'; import { fieldMappings } from './field_mappings'; -import { SampleDatasetSchema } from '../../lib/sample_dataset_registry_types'; +import { SampleDatasetProvider } from '../../lib/sample_dataset_registry_types'; const logsName = i18n.translate('home.sampleData.logsTsdbSpecTitle', { defaultMessage: 'Sample web logs (TSDB)', @@ -20,7 +20,7 @@ const logsDescription = i18n.translate('home.sampleData.logsTsdbSpecDescription' }); export const GLOBE_ICON_PATH = '/plugins/home/assets/sample_data_resources/logs/icon.svg'; -export const logsTSDBSpecProvider = function (): SampleDatasetSchema { +export const logsTSDBSpecProvider: SampleDatasetProvider = ({ staticAssets }) => { const startDate = new Date(); const endDate = new Date(); startDate.setMonth(startDate.getMonth() - 1); @@ -29,8 +29,10 @@ export const logsTSDBSpecProvider = function (): SampleDatasetSchema { id: 'logstsdb', name: logsName, description: logsDescription, - previewImagePath: '/plugins/home/assets/sample_data_resources/logs/dashboard.webp', - darkPreviewImagePath: '/plugins/home/assets/sample_data_resources/logs/dashboard_dark.webp', + previewImagePath: staticAssets.getPluginAssetHref('/sample_data_resources/logs/dashboard.webp'), + darkPreviewImagePath: staticAssets.getPluginAssetHref( + '/sample_data_resources/logs/dashboard_dark.webp' + ), overviewDashboard: 'edf84fe0-e1a0-11e7-b6d5-4dc382ef8f5b', defaultIndex: '90943e30-9a47-11e8-b64d-95841ca0c247', savedObjects: getSavedObjects(), @@ -53,6 +55,6 @@ export const logsTSDBSpecProvider = function (): SampleDatasetSchema { }, ], status: 'not_installed', - iconPath: GLOBE_ICON_PATH, + iconPath: staticAssets.getPluginAssetHref('/sample_data_resources/logs/icon.svg'), }; }; diff --git a/src/plugins/home/server/services/sample_data/lib/sample_dataset_registry_types.ts b/src/plugins/home/server/services/sample_data/lib/sample_dataset_registry_types.ts index 9b1212e13b024..eb248cc4d4078 100644 --- a/src/plugins/home/server/services/sample_data/lib/sample_dataset_registry_types.ts +++ b/src/plugins/home/server/services/sample_data/lib/sample_dataset_registry_types.ts @@ -6,6 +6,7 @@ * Side Public License, v 1. */ +import type { IStaticAssets } from '@kbn/core/server'; import type { SampleDatasetSchema } from './sample_dataset_schema'; export type { SampleDatasetSchema, DataIndexSchema } from './sample_dataset_schema'; @@ -27,7 +28,11 @@ export enum EmbeddableTypes { SEARCH_EMBEDDABLE_TYPE = 'search', VISUALIZE_EMBEDDABLE_TYPE = 'visualization', } -export type SampleDatasetProvider = () => SampleDatasetSchema; + +export interface SampleDatasetProviderContext { + staticAssets: IStaticAssets; +} +export type SampleDatasetProvider = (context: SampleDatasetProviderContext) => SampleDatasetSchema; /** This type is used to identify an object in a sample dataset. */ export interface SampleObject { diff --git a/src/plugins/home/server/services/sample_data/sample_data_registry.ts b/src/plugins/home/server/services/sample_data/sample_data_registry.ts index 47ddc122f82cb..1f96cbe20def2 100644 --- a/src/plugins/home/server/services/sample_data/sample_data_registry.ts +++ b/src/plugins/home/server/services/sample_data/sample_data_registry.ts @@ -15,6 +15,7 @@ import { SampleDatasetSchema, SampleDatasetDashboardPanel, AppLinkData, + SampleDatasetProviderContext, } from './lib/sample_dataset_registry_types'; import { sampleDataSchema } from './lib/sample_dataset_schema'; @@ -34,11 +35,15 @@ export class SampleDataRegistry { private readonly sampleDatasets: SampleDatasetSchema[] = []; private readonly appLinksMap = new Map(); + private sampleDataProviderContext?: SampleDatasetProviderContext; private registerSampleDataSet(specProvider: SampleDatasetProvider) { + if (!this.sampleDataProviderContext) { + throw new Error('#registerSampleDataSet called before #setup'); + } let value: SampleDatasetSchema; try { - value = sampleDataSchema.validate(specProvider()); + value = sampleDataSchema.validate(specProvider(this.sampleDataProviderContext)); } catch (error) { throw new Error(`Unable to register sample dataset spec because it's invalid. ${error}`); } @@ -83,6 +88,10 @@ export class SampleDataRegistry { createInstallRoute(router, this.sampleDatasets, logger, usageTracker, core.analytics); createUninstallRoute(router, this.sampleDatasets, logger, usageTracker, core.analytics); + this.sampleDataProviderContext = { + staticAssets: core.http.staticAssets, + }; + this.registerSampleDataSet(flightsSpecProvider); this.registerSampleDataSet(logsSpecProvider); this.registerSampleDataSet(ecommerceSpecProvider); diff --git a/src/plugins/home/server/services/tutorials/lib/tutorials_registry_types.ts b/src/plugins/home/server/services/tutorials/lib/tutorials_registry_types.ts index f0746764f4641..dd625c6086717 100644 --- a/src/plugins/home/server/services/tutorials/lib/tutorials_registry_types.ts +++ b/src/plugins/home/server/services/tutorials/lib/tutorials_registry_types.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import type { KibanaRequest } from '@kbn/core/server'; +import type { KibanaRequest, IStaticAssets } from '@kbn/core/server'; import type { TutorialSchema } from './tutorial_schema'; export { TutorialsCategory } from '../../../../common/constants'; @@ -25,6 +25,7 @@ export type Platform = 'WINDOWS' | 'OSX' | 'DEB' | 'RPM'; export interface TutorialContext { kibanaBranch: string; + staticAssets: IStaticAssets; [key: string]: unknown; } export type TutorialProvider = (context: TutorialContext) => TutorialSchema; diff --git a/src/plugins/home/server/services/tutorials/tutorials_registry.test.ts b/src/plugins/home/server/services/tutorials/tutorials_registry.test.ts index 5a8c6dc55bda4..c8d9fa9d27aec 100644 --- a/src/plugins/home/server/services/tutorials/tutorials_registry.test.ts +++ b/src/plugins/home/server/services/tutorials/tutorials_registry.test.ts @@ -166,10 +166,9 @@ describe('TutorialsRegistry', () => { describe('start', () => { test('exposes proper contract', () => { - const start = new TutorialsRegistry(mockInitContext).start( - coreMock.createStart(), - mockCustomIntegrationsPluginSetup - ); + const registry = new TutorialsRegistry(mockInitContext); + registry.setup(mockCoreSetup, mockCustomIntegrationsPluginSetup); + const start = registry.start(coreMock.createStart(), mockCustomIntegrationsPluginSetup); expect(start).toBeDefined(); }); }); diff --git a/src/plugins/home/server/services/tutorials/tutorials_registry.ts b/src/plugins/home/server/services/tutorials/tutorials_registry.ts index 0ef800f63228b..eb3c6e931ff60 100644 --- a/src/plugins/home/server/services/tutorials/tutorials_registry.ts +++ b/src/plugins/home/server/services/tutorials/tutorials_registry.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import { CoreSetup, CoreStart, PluginInitializerContext } from '@kbn/core/server'; +import { CoreSetup, CoreStart, PluginInitializerContext, IStaticAssets } from '@kbn/core/server'; import { CustomIntegrationsPluginSetup } from '@kbn/custom-integrations-plugin/server'; import { IntegrationCategory } from '@kbn/custom-integrations-plugin/common'; import { @@ -71,10 +71,13 @@ function registerBeatsTutorialsWithCustomIntegrations( export class TutorialsRegistry { private tutorialProviders: TutorialProvider[] = []; // pre-register all the tutorials we know we want in here private readonly scopedTutorialContextFactories: TutorialContextFactory[] = []; + private staticAssets!: IStaticAssets; constructor(private readonly initContext: PluginInitializerContext) {} public setup(core: CoreSetup, customIntegrations?: CustomIntegrationsPluginSetup) { + this.staticAssets = core.http.staticAssets; + const router = core.http.createRouter(); router.get( { path: '/api/kibana/home/tutorials', validate: false }, @@ -143,7 +146,10 @@ export class TutorialsRegistry { } private get baseTutorialContext(): TutorialContext { - return { kibanaBranch: this.initContext.env.packageInfo.branch }; + return { + kibanaBranch: this.initContext.env.packageInfo.branch, + staticAssets: this.staticAssets, + }; } } diff --git a/src/plugins/home/server/tutorials/activemq_logs/index.ts b/src/plugins/home/server/tutorials/activemq_logs/index.ts index af1a79e445fd8..b152d760bd60f 100644 --- a/src/plugins/home/server/tutorials/activemq_logs/index.ts +++ b/src/plugins/home/server/tutorials/activemq_logs/index.ts @@ -38,7 +38,7 @@ export function activemqLogsSpecProvider(context: TutorialContext): TutorialSche learnMoreLink: '{config.docs.beats.filebeat}/filebeat-module-activemq.html', }, }), - euiIconType: '/plugins/home/assets/logos/activemq.svg', + euiIconType: context.staticAssets.getPluginAssetHref('/logos/activemq.svg'), artifacts: { dashboards: [ { @@ -54,7 +54,7 @@ export function activemqLogsSpecProvider(context: TutorialContext): TutorialSche }, }, completionTimeMinutes: 10, - previewImagePath: '/plugins/home/assets/activemq_logs/screenshot.webp', + previewImagePath: context.staticAssets.getPluginAssetHref('/activemq_logs/screenshot.webp'), onPrem: onPremInstructions(moduleName, platforms, context), elasticCloud: cloudInstructions(moduleName, platforms, context), onPremElasticCloud: onPremCloudInstructions(moduleName, platforms, context), diff --git a/src/plugins/home/server/tutorials/activemq_metrics/index.ts b/src/plugins/home/server/tutorials/activemq_metrics/index.ts index c5c68ba0fe0ea..a255a85fa6960 100644 --- a/src/plugins/home/server/tutorials/activemq_metrics/index.ts +++ b/src/plugins/home/server/tutorials/activemq_metrics/index.ts @@ -38,7 +38,7 @@ export function activemqMetricsSpecProvider(context: TutorialContext): TutorialS learnMoreLink: '{config.docs.beats.metricbeat}/metricbeat-module-activemq.html', }, }), - euiIconType: '/plugins/home/assets/logos/activemq.svg', + euiIconType: context.staticAssets.getPluginAssetHref('/logos/activemq.svg'), isBeta: true, artifacts: { application: { diff --git a/src/plugins/home/server/tutorials/apache_logs/index.ts b/src/plugins/home/server/tutorials/apache_logs/index.ts index 2d729daefdc65..3bd77f587f09d 100644 --- a/src/plugins/home/server/tutorials/apache_logs/index.ts +++ b/src/plugins/home/server/tutorials/apache_logs/index.ts @@ -55,7 +55,7 @@ export function apacheLogsSpecProvider(context: TutorialContext): TutorialSchema }, }, completionTimeMinutes: 10, - previewImagePath: '/plugins/home/assets/apache_logs/screenshot.webp', + previewImagePath: context.staticAssets.getPluginAssetHref('/apache_logs/screenshot.webp'), onPrem: onPremInstructions(moduleName, platforms, context), elasticCloud: cloudInstructions(moduleName, platforms, context), onPremElasticCloud: onPremCloudInstructions(moduleName, platforms, context), diff --git a/src/plugins/home/server/tutorials/apache_metrics/index.ts b/src/plugins/home/server/tutorials/apache_metrics/index.ts index 114483f7414de..a021401890503 100644 --- a/src/plugins/home/server/tutorials/apache_metrics/index.ts +++ b/src/plugins/home/server/tutorials/apache_metrics/index.ts @@ -54,7 +54,7 @@ export function apacheMetricsSpecProvider(context: TutorialContext): TutorialSch }, }, completionTimeMinutes: 10, - previewImagePath: '/plugins/home/assets/apache_metrics/screenshot.webp', + previewImagePath: context.staticAssets.getPluginAssetHref('/apache_metrics/screenshot.webp'), onPrem: onPremInstructions(moduleName, context), elasticCloud: cloudInstructions(moduleName, context), onPremElasticCloud: onPremCloudInstructions(moduleName, context), diff --git a/src/plugins/home/server/tutorials/auditbeat/index.ts b/src/plugins/home/server/tutorials/auditbeat/index.ts index e315398578781..fe9928ff368bb 100644 --- a/src/plugins/home/server/tutorials/auditbeat/index.ts +++ b/src/plugins/home/server/tutorials/auditbeat/index.ts @@ -54,7 +54,7 @@ processes, users, logins, sockets information, file accesses, and more. \ }, }, completionTimeMinutes: 10, - previewImagePath: '/plugins/home/assets/auditbeat/screenshot.webp', + previewImagePath: context.staticAssets.getPluginAssetHref('/auditbeat/screenshot.webp'), onPrem: onPremInstructions(platforms, context), elasticCloud: cloudInstructions(platforms, context), onPremElasticCloud: onPremCloudInstructions(platforms, context), diff --git a/src/plugins/home/server/tutorials/auditd_logs/index.ts b/src/plugins/home/server/tutorials/auditd_logs/index.ts index 383eb46d83a7a..438e847efe337 100644 --- a/src/plugins/home/server/tutorials/auditd_logs/index.ts +++ b/src/plugins/home/server/tutorials/auditd_logs/index.ts @@ -39,7 +39,7 @@ export function auditdLogsSpecProvider(context: TutorialContext): TutorialSchema learnMoreLink: '{config.docs.beats.filebeat}/filebeat-module-auditd.html', }, }), - euiIconType: '/plugins/home/assets/logos/linux.svg', + euiIconType: context.staticAssets.getPluginAssetHref('/logos/linux.svg'), artifacts: { dashboards: [ { @@ -55,7 +55,7 @@ export function auditdLogsSpecProvider(context: TutorialContext): TutorialSchema }, }, completionTimeMinutes: 10, - previewImagePath: '/plugins/home/assets/auditd_logs/screenshot.webp', + previewImagePath: context.staticAssets.getPluginAssetHref('/auditd_logs/screenshot.webp'), onPrem: onPremInstructions(moduleName, platforms, context), elasticCloud: cloudInstructions(moduleName, platforms, context), onPremElasticCloud: onPremCloudInstructions(moduleName, platforms, context), diff --git a/src/plugins/home/server/tutorials/aws_logs/index.ts b/src/plugins/home/server/tutorials/aws_logs/index.ts index dd20d8d282f10..e8c178c040ad3 100644 --- a/src/plugins/home/server/tutorials/aws_logs/index.ts +++ b/src/plugins/home/server/tutorials/aws_logs/index.ts @@ -55,7 +55,7 @@ export function awsLogsSpecProvider(context: TutorialContext): TutorialSchema { }, }, completionTimeMinutes: 10, - previewImagePath: '/plugins/home/assets/aws_logs/screenshot.webp', + previewImagePath: context.staticAssets.getPluginAssetHref('/aws_logs/screenshot.webp'), onPrem: onPremInstructions(moduleName, platforms, context), elasticCloud: cloudInstructions(moduleName, platforms, context), onPremElasticCloud: onPremCloudInstructions(moduleName, platforms, context), diff --git a/src/plugins/home/server/tutorials/aws_metrics/index.ts b/src/plugins/home/server/tutorials/aws_metrics/index.ts index cdc4a3970b426..d5bf865b79026 100644 --- a/src/plugins/home/server/tutorials/aws_metrics/index.ts +++ b/src/plugins/home/server/tutorials/aws_metrics/index.ts @@ -56,7 +56,7 @@ export function awsMetricsSpecProvider(context: TutorialContext): TutorialSchema }, }, completionTimeMinutes: 10, - previewImagePath: '/plugins/home/assets/aws_metrics/screenshot.webp', + previewImagePath: context.staticAssets.getPluginAssetHref('/aws_metrics/screenshot.webp'), onPrem: onPremInstructions(moduleName, context), elasticCloud: cloudInstructions(moduleName, context), onPremElasticCloud: onPremCloudInstructions(moduleName, context), diff --git a/src/plugins/home/server/tutorials/azure_logs/index.ts b/src/plugins/home/server/tutorials/azure_logs/index.ts index 8efa2cea888ec..62f75a3eb0537 100644 --- a/src/plugins/home/server/tutorials/azure_logs/index.ts +++ b/src/plugins/home/server/tutorials/azure_logs/index.ts @@ -56,7 +56,7 @@ export function azureLogsSpecProvider(context: TutorialContext): TutorialSchema }, }, completionTimeMinutes: 10, - previewImagePath: '/plugins/home/assets/azure_logs/screenshot.webp', + previewImagePath: context.staticAssets.getPluginAssetHref('/azure_logs/screenshot.webp'), onPrem: onPremInstructions(moduleName, platforms, context), elasticCloud: cloudInstructions(moduleName, platforms, context), onPremElasticCloud: onPremCloudInstructions(moduleName, platforms, context), diff --git a/src/plugins/home/server/tutorials/azure_metrics/index.ts b/src/plugins/home/server/tutorials/azure_metrics/index.ts index 32f9840b9ed65..59492f6704ac8 100644 --- a/src/plugins/home/server/tutorials/azure_metrics/index.ts +++ b/src/plugins/home/server/tutorials/azure_metrics/index.ts @@ -55,7 +55,7 @@ export function azureMetricsSpecProvider(context: TutorialContext): TutorialSche }, }, completionTimeMinutes: 10, - previewImagePath: '/plugins/home/assets/azure_metrics/screenshot.webp', + previewImagePath: context.staticAssets.getPluginAssetHref('/azure_metrics/screenshot.webp'), onPrem: onPremInstructions(moduleName, context), elasticCloud: cloudInstructions(moduleName, context), onPremElasticCloud: onPremCloudInstructions(moduleName, context), diff --git a/src/plugins/home/server/tutorials/barracuda_logs/index.ts b/src/plugins/home/server/tutorials/barracuda_logs/index.ts index 70daca5656a66..d91b77495dca2 100644 --- a/src/plugins/home/server/tutorials/barracuda_logs/index.ts +++ b/src/plugins/home/server/tutorials/barracuda_logs/index.ts @@ -40,7 +40,7 @@ export function barracudaLogsSpecProvider(context: TutorialContext): TutorialSch learnMoreLink: '{config.docs.beats.filebeat}/filebeat-module-barracuda.html', }, }), - euiIconType: '/plugins/home/assets/logos/barracuda.svg', + euiIconType: context.staticAssets.getPluginAssetHref('/logos/barracuda.svg'), artifacts: { dashboards: [], application: { diff --git a/src/plugins/home/server/tutorials/checkpoint_logs/index.ts b/src/plugins/home/server/tutorials/checkpoint_logs/index.ts index 3fa333c218396..bd7457f0157f5 100644 --- a/src/plugins/home/server/tutorials/checkpoint_logs/index.ts +++ b/src/plugins/home/server/tutorials/checkpoint_logs/index.ts @@ -39,7 +39,7 @@ export function checkpointLogsSpecProvider(context: TutorialContext): TutorialSc learnMoreLink: '{config.docs.beats.filebeat}/filebeat-module-checkpoint.html', }, }), - euiIconType: '/plugins/home/assets/logos/checkpoint.svg', + euiIconType: context.staticAssets.getPluginAssetHref('/logos/checkpoint.svg'), artifacts: { dashboards: [], application: { diff --git a/src/plugins/home/server/tutorials/cisco_logs/index.ts b/src/plugins/home/server/tutorials/cisco_logs/index.ts index 098819c14297f..c125c283702d9 100644 --- a/src/plugins/home/server/tutorials/cisco_logs/index.ts +++ b/src/plugins/home/server/tutorials/cisco_logs/index.ts @@ -39,7 +39,7 @@ export function ciscoLogsSpecProvider(context: TutorialContext): TutorialSchema learnMoreLink: '{config.docs.beats.filebeat}/filebeat-module-cisco.html', }, }), - euiIconType: '/plugins/home/assets/logos/cisco.svg', + euiIconType: context.staticAssets.getPluginAssetHref('/logos/cisco.svg'), artifacts: { dashboards: [ { @@ -55,7 +55,7 @@ export function ciscoLogsSpecProvider(context: TutorialContext): TutorialSchema }, }, completionTimeMinutes: 10, - previewImagePath: '/plugins/home/assets/cisco_logs/screenshot.webp', + previewImagePath: context.staticAssets.getPluginAssetHref('/cisco_logs/screenshot.webp'), onPrem: onPremInstructions(moduleName, platforms, context), elasticCloud: cloudInstructions(moduleName, platforms, context), onPremElasticCloud: onPremCloudInstructions(moduleName, platforms, context), diff --git a/src/plugins/home/server/tutorials/cockroachdb_metrics/index.ts b/src/plugins/home/server/tutorials/cockroachdb_metrics/index.ts index 1d5cbd95d67f5..14c1d2c1b9c19 100644 --- a/src/plugins/home/server/tutorials/cockroachdb_metrics/index.ts +++ b/src/plugins/home/server/tutorials/cockroachdb_metrics/index.ts @@ -38,7 +38,7 @@ export function cockroachdbMetricsSpecProvider(context: TutorialContext): Tutori learnMoreLink: '{config.docs.beats.metricbeat}/metricbeat-module-cockroachdb.html', }, }), - euiIconType: '/plugins/home/assets/logos/cockroachdb.svg', + euiIconType: context.staticAssets.getPluginAssetHref('/logos/cockroachdb.svg'), artifacts: { dashboards: [ { @@ -57,7 +57,9 @@ export function cockroachdbMetricsSpecProvider(context: TutorialContext): Tutori }, }, completionTimeMinutes: 10, - previewImagePath: '/plugins/home/assets/cockroachdb_metrics/screenshot.webp', + previewImagePath: context.staticAssets.getPluginAssetHref( + '/cockroachdb_metrics/screenshot.webp' + ), onPrem: onPremInstructions(moduleName, context), elasticCloud: cloudInstructions(moduleName, context), onPremElasticCloud: onPremCloudInstructions(moduleName, context), diff --git a/src/plugins/home/server/tutorials/consul_metrics/index.ts b/src/plugins/home/server/tutorials/consul_metrics/index.ts index bc1d1b6f1d1ea..64b7cb80e8813 100644 --- a/src/plugins/home/server/tutorials/consul_metrics/index.ts +++ b/src/plugins/home/server/tutorials/consul_metrics/index.ts @@ -38,7 +38,7 @@ export function consulMetricsSpecProvider(context: TutorialContext): TutorialSch learnMoreLink: '{config.docs.beats.metricbeat}/metricbeat-module-consul.html', }, }), - euiIconType: '/plugins/home/assets/logos/consul.svg', + euiIconType: context.staticAssets.getPluginAssetHref('/logos/consul.svg'), artifacts: { dashboards: [ { @@ -54,7 +54,7 @@ export function consulMetricsSpecProvider(context: TutorialContext): TutorialSch }, }, completionTimeMinutes: 10, - previewImagePath: '/plugins/home/assets/consul_metrics/screenshot.webp', + previewImagePath: context.staticAssets.getPluginAssetHref('/consul_metrics/screenshot.webp'), onPrem: onPremInstructions(moduleName, context), elasticCloud: cloudInstructions(moduleName, context), onPremElasticCloud: onPremCloudInstructions(moduleName, context), diff --git a/src/plugins/home/server/tutorials/coredns_logs/index.ts b/src/plugins/home/server/tutorials/coredns_logs/index.ts index fedea213c0087..a740144e07400 100644 --- a/src/plugins/home/server/tutorials/coredns_logs/index.ts +++ b/src/plugins/home/server/tutorials/coredns_logs/index.ts @@ -39,7 +39,7 @@ export function corednsLogsSpecProvider(context: TutorialContext): TutorialSchem learnMoreLink: '{config.docs.beats.filebeat}/filebeat-module-coredns.html', }, }), - euiIconType: '/plugins/home/assets/logos/coredns.svg', + euiIconType: context.staticAssets.getPluginAssetHref('/logos/coredns.svg'), artifacts: { dashboards: [ { @@ -55,7 +55,7 @@ export function corednsLogsSpecProvider(context: TutorialContext): TutorialSchem }, }, completionTimeMinutes: 10, - previewImagePath: '/plugins/home/assets/coredns_logs/screenshot.webp', + previewImagePath: context.staticAssets.getPluginAssetHref('/coredns_logs/screenshot.webp'), onPrem: onPremInstructions(moduleName, platforms, context), elasticCloud: cloudInstructions(moduleName, platforms, context), onPremElasticCloud: onPremCloudInstructions(moduleName, platforms, context), diff --git a/src/plugins/home/server/tutorials/coredns_metrics/index.ts b/src/plugins/home/server/tutorials/coredns_metrics/index.ts index b3e5de7fb58a8..82f1205971aac 100644 --- a/src/plugins/home/server/tutorials/coredns_metrics/index.ts +++ b/src/plugins/home/server/tutorials/coredns_metrics/index.ts @@ -38,7 +38,7 @@ export function corednsMetricsSpecProvider(context: TutorialContext): TutorialSc learnMoreLink: '{config.docs.beats.metricbeat}/metricbeat-module-coredns.html', }, }), - euiIconType: '/plugins/home/assets/logos/coredns.svg', + euiIconType: context.staticAssets.getPluginAssetHref('/logos/coredns.svg'), artifacts: { application: { label: i18n.translate('home.tutorials.corednsMetrics.artifacts.application.label', { @@ -52,7 +52,7 @@ export function corednsMetricsSpecProvider(context: TutorialContext): TutorialSc }, }, completionTimeMinutes: 10, - previewImagePath: '/plugins/home/assets/coredns_metrics/screenshot.webp', + previewImagePath: context.staticAssets.getPluginAssetHref('/coredns_metrics/screenshot.webp'), onPrem: onPremInstructions(moduleName, context), elasticCloud: cloudInstructions(moduleName, context), onPremElasticCloud: onPremCloudInstructions(moduleName, context), diff --git a/src/plugins/home/server/tutorials/couchdb_metrics/index.ts b/src/plugins/home/server/tutorials/couchdb_metrics/index.ts index 59f8431fe6a08..c63d9a045f590 100644 --- a/src/plugins/home/server/tutorials/couchdb_metrics/index.ts +++ b/src/plugins/home/server/tutorials/couchdb_metrics/index.ts @@ -38,7 +38,7 @@ export function couchdbMetricsSpecProvider(context: TutorialContext): TutorialSc learnMoreLink: '{config.docs.beats.metricbeat}/metricbeat-module-couchdb.html', }, }), - euiIconType: '/plugins/home/assets/logos/couchdb.svg', + euiIconType: context.staticAssets.getPluginAssetHref('/logos/couchdb.svg'), artifacts: { dashboards: [ { @@ -57,7 +57,7 @@ export function couchdbMetricsSpecProvider(context: TutorialContext): TutorialSc }, }, completionTimeMinutes: 10, - previewImagePath: '/plugins/home/assets/couchdb_metrics/screenshot.webp', + previewImagePath: context.staticAssets.getPluginAssetHref('/couchdb_metrics/screenshot.webp'), onPrem: onPremInstructions(moduleName, context), elasticCloud: cloudInstructions(moduleName, context), onPremElasticCloud: onPremCloudInstructions(moduleName, context), diff --git a/src/plugins/home/server/tutorials/crowdstrike_logs/index.ts b/src/plugins/home/server/tutorials/crowdstrike_logs/index.ts index f55d84e7b58c9..566624d8252b1 100644 --- a/src/plugins/home/server/tutorials/crowdstrike_logs/index.ts +++ b/src/plugins/home/server/tutorials/crowdstrike_logs/index.ts @@ -43,7 +43,7 @@ export function crowdstrikeLogsSpecProvider(context: TutorialContext): TutorialS learnMoreLink: '{config.docs.beats.filebeat}/filebeat-module-crowdstrike.html', }, }), - euiIconType: '/plugins/home/assets/logos/crowdstrike.svg', + euiIconType: context.staticAssets.getPluginAssetHref('/logos/crowdstrike.svg'), artifacts: { dashboards: [], application: { diff --git a/src/plugins/home/server/tutorials/cylance_logs/index.ts b/src/plugins/home/server/tutorials/cylance_logs/index.ts index 805391dc4d364..e1781fa69df5d 100644 --- a/src/plugins/home/server/tutorials/cylance_logs/index.ts +++ b/src/plugins/home/server/tutorials/cylance_logs/index.ts @@ -39,7 +39,7 @@ export function cylanceLogsSpecProvider(context: TutorialContext): TutorialSchem learnMoreLink: '{config.docs.beats.filebeat}/filebeat-module-cylance.html', }, }), - euiIconType: '/plugins/home/assets/logos/cylance.svg', + euiIconType: context.staticAssets.getPluginAssetHref('/logos/cylance.svg'), artifacts: { dashboards: [], application: { diff --git a/src/plugins/home/server/tutorials/docker_metrics/index.ts b/src/plugins/home/server/tutorials/docker_metrics/index.ts index 180723079acba..6f683c7eb9b77 100644 --- a/src/plugins/home/server/tutorials/docker_metrics/index.ts +++ b/src/plugins/home/server/tutorials/docker_metrics/index.ts @@ -54,7 +54,7 @@ export function dockerMetricsSpecProvider(context: TutorialContext): TutorialSch }, }, completionTimeMinutes: 10, - previewImagePath: '/plugins/home/assets/docker_metrics/screenshot.webp', + previewImagePath: context.staticAssets.getPluginAssetHref('/docker_metrics/screenshot.webp'), onPrem: onPremInstructions(moduleName, context), elasticCloud: cloudInstructions(moduleName, context), onPremElasticCloud: onPremCloudInstructions(moduleName, context), diff --git a/src/plugins/home/server/tutorials/elasticsearch_logs/index.ts b/src/plugins/home/server/tutorials/elasticsearch_logs/index.ts index bdcc65ead4182..1763a434d4906 100644 --- a/src/plugins/home/server/tutorials/elasticsearch_logs/index.ts +++ b/src/plugins/home/server/tutorials/elasticsearch_logs/index.ts @@ -54,7 +54,9 @@ export function elasticsearchLogsSpecProvider(context: TutorialContext): Tutoria }, }, completionTimeMinutes: 10, - previewImagePath: '/plugins/home/assets/elasticsearch_logs/screenshot.webp', + previewImagePath: context.staticAssets.getPluginAssetHref( + '/elasticsearch_logs/screenshot.webp' + ), onPrem: onPremInstructions(moduleName, platforms, context), elasticCloud: cloudInstructions(moduleName, platforms, context), onPremElasticCloud: onPremCloudInstructions(moduleName, platforms, context), diff --git a/src/plugins/home/server/tutorials/envoyproxy_logs/index.ts b/src/plugins/home/server/tutorials/envoyproxy_logs/index.ts index 06f0587e1021d..aa071297ed978 100644 --- a/src/plugins/home/server/tutorials/envoyproxy_logs/index.ts +++ b/src/plugins/home/server/tutorials/envoyproxy_logs/index.ts @@ -39,7 +39,7 @@ export function envoyproxyLogsSpecProvider(context: TutorialContext): TutorialSc learnMoreLink: '{config.docs.beats.filebeat}/filebeat-module-envoyproxy.html', }, }), - euiIconType: '/plugins/home/assets/logos/envoyproxy.svg', + euiIconType: context.staticAssets.getPluginAssetHref('/logos/envoyproxy.svg'), artifacts: { dashboards: [ { @@ -58,7 +58,7 @@ export function envoyproxyLogsSpecProvider(context: TutorialContext): TutorialSc }, }, completionTimeMinutes: 10, - previewImagePath: '/plugins/home/assets/envoyproxy_logs/screenshot.webp', + previewImagePath: context.staticAssets.getPluginAssetHref('/envoyproxy_logs/screenshot.webp'), onPrem: onPremInstructions(moduleName, platforms, context), elasticCloud: cloudInstructions(moduleName, platforms, context), onPremElasticCloud: onPremCloudInstructions(moduleName, platforms, context), diff --git a/src/plugins/home/server/tutorials/envoyproxy_metrics/index.ts b/src/plugins/home/server/tutorials/envoyproxy_metrics/index.ts index 03bc5d13baf9c..8c4396ff90ba0 100644 --- a/src/plugins/home/server/tutorials/envoyproxy_metrics/index.ts +++ b/src/plugins/home/server/tutorials/envoyproxy_metrics/index.ts @@ -38,7 +38,7 @@ export function envoyproxyMetricsSpecProvider(context: TutorialContext): Tutoria learnMoreLink: '{config.docs.beats.metricbeat}/metricbeat-module-envoyproxy.html', }, }), - euiIconType: '/plugins/home/assets/logos/envoyproxy.svg', + euiIconType: context.staticAssets.getPluginAssetHref('/logos/envoyproxy.svg'), artifacts: { dashboards: [], exportedFields: { diff --git a/src/plugins/home/server/tutorials/f5_logs/index.ts b/src/plugins/home/server/tutorials/f5_logs/index.ts index ae596b52a538b..e79018c6b58e4 100644 --- a/src/plugins/home/server/tutorials/f5_logs/index.ts +++ b/src/plugins/home/server/tutorials/f5_logs/index.ts @@ -39,7 +39,7 @@ export function f5LogsSpecProvider(context: TutorialContext): TutorialSchema { learnMoreLink: '{config.docs.beats.filebeat}/filebeat-module-f5.html', }, }), - euiIconType: '/plugins/home/assets/logos/f5.svg', + euiIconType: context.staticAssets.getPluginAssetHref('/logos/f5.svg'), artifacts: { dashboards: [], application: { @@ -53,7 +53,7 @@ export function f5LogsSpecProvider(context: TutorialContext): TutorialSchema { }, }, completionTimeMinutes: 10, - previewImagePath: '/plugins/home/assets/f5_logs/screenshot.webp', + previewImagePath: context.staticAssets.getPluginAssetHref('/f5_logs/screenshot.webp'), onPrem: onPremInstructions(moduleName, platforms, context), elasticCloud: cloudInstructions(moduleName, platforms, context), onPremElasticCloud: onPremCloudInstructions(moduleName, platforms, context), diff --git a/src/plugins/home/server/tutorials/fortinet_logs/index.ts b/src/plugins/home/server/tutorials/fortinet_logs/index.ts index 32338480fb009..4128f7460b90d 100644 --- a/src/plugins/home/server/tutorials/fortinet_logs/index.ts +++ b/src/plugins/home/server/tutorials/fortinet_logs/index.ts @@ -39,7 +39,7 @@ export function fortinetLogsSpecProvider(context: TutorialContext): TutorialSche learnMoreLink: '{config.docs.beats.filebeat}/filebeat-module-fortinet.html', }, }), - euiIconType: '/plugins/home/assets/logos/fortinet.svg', + euiIconType: context.staticAssets.getPluginAssetHref('/logos/fortinet.svg'), artifacts: { dashboards: [], application: { diff --git a/src/plugins/home/server/tutorials/gcp_logs/index.ts b/src/plugins/home/server/tutorials/gcp_logs/index.ts index 6c33ac1fbaa0b..bc0fa1de8184e 100644 --- a/src/plugins/home/server/tutorials/gcp_logs/index.ts +++ b/src/plugins/home/server/tutorials/gcp_logs/index.ts @@ -57,7 +57,7 @@ export function gcpLogsSpecProvider(context: TutorialContext): TutorialSchema { }, }, completionTimeMinutes: 10, - previewImagePath: '/plugins/home/assets/gcp_logs/screenshot.webp', + previewImagePath: context.staticAssets.getPluginAssetHref('/gcp_logs/screenshot.webp'), onPrem: onPremInstructions(moduleName, platforms, context), elasticCloud: cloudInstructions(moduleName, platforms, context), onPremElasticCloud: onPremCloudInstructions(moduleName, platforms, context), diff --git a/src/plugins/home/server/tutorials/gcp_metrics/index.ts b/src/plugins/home/server/tutorials/gcp_metrics/index.ts index 649fd54dbde52..4b9fc9c23e790 100644 --- a/src/plugins/home/server/tutorials/gcp_metrics/index.ts +++ b/src/plugins/home/server/tutorials/gcp_metrics/index.ts @@ -55,7 +55,7 @@ export function gcpMetricsSpecProvider(context: TutorialContext): TutorialSchema }, }, completionTimeMinutes: 10, - previewImagePath: '/plugins/home/assets/gcp_metrics/screenshot.webp', + previewImagePath: context.staticAssets.getPluginAssetHref('/gcp_metrics/screenshot.webp'), onPrem: onPremInstructions(moduleName, context), elasticCloud: cloudInstructions(moduleName, context), onPremElasticCloud: onPremCloudInstructions(moduleName, context), diff --git a/src/plugins/home/server/tutorials/haproxy_logs/index.ts b/src/plugins/home/server/tutorials/haproxy_logs/index.ts index 6d83b9c544994..4cfa85570d8f5 100644 --- a/src/plugins/home/server/tutorials/haproxy_logs/index.ts +++ b/src/plugins/home/server/tutorials/haproxy_logs/index.ts @@ -55,7 +55,7 @@ export function haproxyLogsSpecProvider(context: TutorialContext): TutorialSchem }, }, completionTimeMinutes: 10, - previewImagePath: '/plugins/home/assets/haproxy_logs/screenshot.webp', + previewImagePath: context.staticAssets.getPluginAssetHref('/haproxy_logs/screenshot.webp'), onPrem: onPremInstructions(moduleName, platforms, context), elasticCloud: cloudInstructions(moduleName, platforms, context), onPremElasticCloud: onPremCloudInstructions(moduleName, platforms, context), diff --git a/src/plugins/home/server/tutorials/ibmmq_logs/index.ts b/src/plugins/home/server/tutorials/ibmmq_logs/index.ts index fd3327a555b41..0ca37ece3584c 100644 --- a/src/plugins/home/server/tutorials/ibmmq_logs/index.ts +++ b/src/plugins/home/server/tutorials/ibmmq_logs/index.ts @@ -38,7 +38,7 @@ export function ibmmqLogsSpecProvider(context: TutorialContext): TutorialSchema learnMoreLink: '{config.docs.beats.filebeat}/filebeat-module-ibmmq.html', }, }), - euiIconType: '/plugins/home/assets/logos/ibmmq.svg', + euiIconType: context.staticAssets.getPluginAssetHref('/logos/ibmmq.svg'), artifacts: { dashboards: [ { @@ -54,7 +54,7 @@ export function ibmmqLogsSpecProvider(context: TutorialContext): TutorialSchema }, }, completionTimeMinutes: 10, - previewImagePath: '/plugins/home/assets/ibmmq_logs/screenshot.webp', + previewImagePath: context.staticAssets.getPluginAssetHref('/ibmmq_logs/screenshot.webp'), onPrem: onPremInstructions(moduleName, platforms, context), elasticCloud: cloudInstructions(moduleName, platforms, context), onPremElasticCloud: onPremCloudInstructions(moduleName, platforms, context), diff --git a/src/plugins/home/server/tutorials/ibmmq_metrics/index.ts b/src/plugins/home/server/tutorials/ibmmq_metrics/index.ts index 6b81919ce2814..b6411f1b0bff1 100644 --- a/src/plugins/home/server/tutorials/ibmmq_metrics/index.ts +++ b/src/plugins/home/server/tutorials/ibmmq_metrics/index.ts @@ -38,7 +38,7 @@ export function ibmmqMetricsSpecProvider(context: TutorialContext): TutorialSche learnMoreLink: '{config.docs.beats.metricbeat}/metricbeat-module-ibmmq.html', }, }), - euiIconType: '/plugins/home/assets/logos/ibmmq.svg', + euiIconType: context.staticAssets.getPluginAssetHref('/logos/ibmmq.svg'), isBeta: true, artifacts: { application: { @@ -53,7 +53,7 @@ export function ibmmqMetricsSpecProvider(context: TutorialContext): TutorialSche }, }, completionTimeMinutes: 10, - previewImagePath: '/plugins/home/assets/ibmmq_metrics/screenshot.webp', + previewImagePath: context.staticAssets.getPluginAssetHref('/ibmmq_metrics/screenshot.webp'), onPrem: onPremInstructions(moduleName, context), elasticCloud: cloudInstructions(moduleName, context), onPremElasticCloud: onPremCloudInstructions(moduleName, context), diff --git a/src/plugins/home/server/tutorials/icinga_logs/index.ts b/src/plugins/home/server/tutorials/icinga_logs/index.ts index b8d51b1a1809f..c1cf308543429 100644 --- a/src/plugins/home/server/tutorials/icinga_logs/index.ts +++ b/src/plugins/home/server/tutorials/icinga_logs/index.ts @@ -39,7 +39,7 @@ export function icingaLogsSpecProvider(context: TutorialContext): TutorialSchema learnMoreLink: '{config.docs.beats.filebeat}/filebeat-module-icinga.html', }, }), - euiIconType: '/plugins/home/assets/logos/icinga.svg', + euiIconType: context.staticAssets.getPluginAssetHref('/logos/icinga.svg'), artifacts: { dashboards: [ { @@ -55,7 +55,7 @@ export function icingaLogsSpecProvider(context: TutorialContext): TutorialSchema }, }, completionTimeMinutes: 10, - previewImagePath: '/plugins/home/assets/icinga_logs/screenshot.webp', + previewImagePath: context.staticAssets.getPluginAssetHref('/icinga_logs/screenshot.webp'), onPrem: onPremInstructions(moduleName, platforms, context), elasticCloud: cloudInstructions(moduleName, platforms, context), onPremElasticCloud: onPremCloudInstructions(moduleName, platforms, context), diff --git a/src/plugins/home/server/tutorials/iis_logs/index.ts b/src/plugins/home/server/tutorials/iis_logs/index.ts index 1b7af958d4f9e..1ce2657b50923 100644 --- a/src/plugins/home/server/tutorials/iis_logs/index.ts +++ b/src/plugins/home/server/tutorials/iis_logs/index.ts @@ -40,7 +40,7 @@ export function iisLogsSpecProvider(context: TutorialContext): TutorialSchema { learnMoreLink: '{config.docs.beats.filebeat}/filebeat-module-iis.html', }, }), - euiIconType: '/plugins/home/assets/logos/iis.svg', + euiIconType: context.staticAssets.getPluginAssetHref('/logos/iis.svg'), artifacts: { dashboards: [ { @@ -56,7 +56,7 @@ export function iisLogsSpecProvider(context: TutorialContext): TutorialSchema { }, }, completionTimeMinutes: 10, - previewImagePath: '/plugins/home/assets/iis_logs/screenshot.webp', + previewImagePath: context.staticAssets.getPluginAssetHref('/iis_logs/screenshot.webp'), onPrem: onPremInstructions(moduleName, platforms, context), elasticCloud: cloudInstructions(moduleName, platforms, context), onPremElasticCloud: onPremCloudInstructions(moduleName, platforms, context), diff --git a/src/plugins/home/server/tutorials/iis_metrics/index.ts b/src/plugins/home/server/tutorials/iis_metrics/index.ts index 68f167c7be04d..052b90c0719bb 100644 --- a/src/plugins/home/server/tutorials/iis_metrics/index.ts +++ b/src/plugins/home/server/tutorials/iis_metrics/index.ts @@ -39,7 +39,7 @@ export function iisMetricsSpecProvider(context: TutorialContext): TutorialSchema }, }), isBeta: true, - euiIconType: '/plugins/home/assets/logos/iis.svg', + euiIconType: context.staticAssets.getPluginAssetHref('/logos/iis.svg'), artifacts: { dashboards: [ { @@ -55,7 +55,7 @@ export function iisMetricsSpecProvider(context: TutorialContext): TutorialSchema }, }, completionTimeMinutes: 10, - previewImagePath: '/plugins/home/assets/iis_metrics/screenshot.webp', + previewImagePath: context.staticAssets.getPluginAssetHref('/iis_metrics/screenshot.webp'), onPrem: onPremInstructions(moduleName, context), elasticCloud: cloudInstructions(moduleName, context), onPremElasticCloud: onPremCloudInstructions(moduleName, context), diff --git a/src/plugins/home/server/tutorials/infoblox_logs/index.ts b/src/plugins/home/server/tutorials/infoblox_logs/index.ts index ad82d25993dca..f86ccbf0084b6 100644 --- a/src/plugins/home/server/tutorials/infoblox_logs/index.ts +++ b/src/plugins/home/server/tutorials/infoblox_logs/index.ts @@ -39,7 +39,7 @@ export function infobloxLogsSpecProvider(context: TutorialContext): TutorialSche learnMoreLink: '{config.docs.beats.filebeat}/filebeat-module-infoblox.html', }, }), - euiIconType: '/plugins/home/assets/logos/infoblox.svg', + euiIconType: context.staticAssets.getPluginAssetHref('/logos/infoblox.svg'), artifacts: { dashboards: [], application: { diff --git a/src/plugins/home/server/tutorials/iptables_logs/index.ts b/src/plugins/home/server/tutorials/iptables_logs/index.ts index 082b0a239714a..856a8b0331482 100644 --- a/src/plugins/home/server/tutorials/iptables_logs/index.ts +++ b/src/plugins/home/server/tutorials/iptables_logs/index.ts @@ -42,7 +42,7 @@ export function iptablesLogsSpecProvider(context: TutorialContext): TutorialSche learnMoreLink: '{config.docs.beats.filebeat}/filebeat-module-iptables.html', }, }), - euiIconType: '/plugins/home/assets/logos/linux.svg', + euiIconType: context.staticAssets.getPluginAssetHref('/logos/linux.svg'), artifacts: { dashboards: [ { @@ -58,7 +58,7 @@ export function iptablesLogsSpecProvider(context: TutorialContext): TutorialSche }, }, completionTimeMinutes: 10, - previewImagePath: '/plugins/home/assets/iptables_logs/screenshot.webp', + previewImagePath: context.staticAssets.getPluginAssetHref('/iptables_logs/screenshot.webp'), onPrem: onPremInstructions(moduleName, platforms, context), elasticCloud: cloudInstructions(moduleName, platforms, context), onPremElasticCloud: onPremCloudInstructions(moduleName, platforms, context), diff --git a/src/plugins/home/server/tutorials/juniper_logs/index.ts b/src/plugins/home/server/tutorials/juniper_logs/index.ts index a6d34d1e8447f..04d2e708aeab3 100644 --- a/src/plugins/home/server/tutorials/juniper_logs/index.ts +++ b/src/plugins/home/server/tutorials/juniper_logs/index.ts @@ -39,7 +39,7 @@ export function juniperLogsSpecProvider(context: TutorialContext): TutorialSchem learnMoreLink: '{config.docs.beats.filebeat}/filebeat-module-juniper.html', }, }), - euiIconType: '/plugins/home/assets/logos/juniper.svg', + euiIconType: context.staticAssets.getPluginAssetHref('/logos/juniper.svg'), artifacts: { dashboards: [], application: { diff --git a/src/plugins/home/server/tutorials/kafka_logs/index.ts b/src/plugins/home/server/tutorials/kafka_logs/index.ts index cb78ffbaeaea7..a4918995965c6 100644 --- a/src/plugins/home/server/tutorials/kafka_logs/index.ts +++ b/src/plugins/home/server/tutorials/kafka_logs/index.ts @@ -55,7 +55,7 @@ export function kafkaLogsSpecProvider(context: TutorialContext): TutorialSchema }, }, completionTimeMinutes: 10, - previewImagePath: '/plugins/home/assets/kafka_logs/screenshot.webp', + previewImagePath: context.staticAssets.getPluginAssetHref('/kafka_logs/screenshot.webp'), onPrem: onPremInstructions(moduleName, platforms, context), elasticCloud: cloudInstructions(moduleName, platforms, context), onPremElasticCloud: onPremCloudInstructions(moduleName, platforms, context), diff --git a/src/plugins/home/server/tutorials/kubernetes_metrics/index.ts b/src/plugins/home/server/tutorials/kubernetes_metrics/index.ts index bb40e88e7541d..6db2731349e23 100644 --- a/src/plugins/home/server/tutorials/kubernetes_metrics/index.ts +++ b/src/plugins/home/server/tutorials/kubernetes_metrics/index.ts @@ -57,7 +57,9 @@ export function kubernetesMetricsSpecProvider(context: TutorialContext): Tutoria }, }, completionTimeMinutes: 10, - previewImagePath: '/plugins/home/assets/kubernetes_metrics/screenshot.webp', + previewImagePath: context.staticAssets.getPluginAssetHref( + '/kubernetes_metrics/screenshot.webp' + ), onPrem: onPremInstructions(moduleName, context), elasticCloud: cloudInstructions(moduleName, context), onPremElasticCloud: onPremCloudInstructions(moduleName, context), diff --git a/src/plugins/home/server/tutorials/microsoft_logs/index.ts b/src/plugins/home/server/tutorials/microsoft_logs/index.ts index fc8926df08420..bc7eb73f60625 100644 --- a/src/plugins/home/server/tutorials/microsoft_logs/index.ts +++ b/src/plugins/home/server/tutorials/microsoft_logs/index.ts @@ -39,7 +39,7 @@ export function microsoftLogsSpecProvider(context: TutorialContext): TutorialSch learnMoreLink: '{config.docs.beats.filebeat}/filebeat-module-microsoft.html', }, }), - euiIconType: '/plugins/home/assets/logos/microsoft.svg', + euiIconType: context.staticAssets.getPluginAssetHref('/logos/microsoft.svg'), artifacts: { dashboards: [ { @@ -55,7 +55,7 @@ export function microsoftLogsSpecProvider(context: TutorialContext): TutorialSch }, }, completionTimeMinutes: 10, - previewImagePath: '/plugins/home/assets/microsoft_logs/screenshot.webp', + previewImagePath: context.staticAssets.getPluginAssetHref('/microsoft_logs/screenshot.webp'), onPrem: onPremInstructions(moduleName, platforms, context), elasticCloud: cloudInstructions(moduleName, platforms, context), onPremElasticCloud: onPremCloudInstructions(moduleName, platforms, context), diff --git a/src/plugins/home/server/tutorials/misp_logs/index.ts b/src/plugins/home/server/tutorials/misp_logs/index.ts index 7cb31f8db3a46..3fcd6f35faae9 100644 --- a/src/plugins/home/server/tutorials/misp_logs/index.ts +++ b/src/plugins/home/server/tutorials/misp_logs/index.ts @@ -39,7 +39,7 @@ export function mispLogsSpecProvider(context: TutorialContext): TutorialSchema { learnMoreLink: '{config.docs.beats.filebeat}/filebeat-module-misp.html', }, }), - euiIconType: '/plugins/home/assets/logos/misp.svg', + euiIconType: context.staticAssets.getPluginAssetHref('/logos/misp.svg'), artifacts: { dashboards: [ { @@ -55,7 +55,7 @@ export function mispLogsSpecProvider(context: TutorialContext): TutorialSchema { }, }, completionTimeMinutes: 10, - previewImagePath: '/plugins/home/assets/misp_logs/screenshot.webp', + previewImagePath: context.staticAssets.getPluginAssetHref('/misp_logs/screenshot.webp'), onPrem: onPremInstructions(moduleName, platforms, context), elasticCloud: cloudInstructions(moduleName, platforms, context), onPremElasticCloud: onPremCloudInstructions(moduleName, platforms, context), diff --git a/src/plugins/home/server/tutorials/mongodb_logs/index.ts b/src/plugins/home/server/tutorials/mongodb_logs/index.ts index 3f2618d15c844..4cd48e2af715c 100644 --- a/src/plugins/home/server/tutorials/mongodb_logs/index.ts +++ b/src/plugins/home/server/tutorials/mongodb_logs/index.ts @@ -55,7 +55,7 @@ export function mongodbLogsSpecProvider(context: TutorialContext): TutorialSchem }, }, completionTimeMinutes: 10, - previewImagePath: '/plugins/home/assets/mongodb_logs/screenshot.webp', + previewImagePath: context.staticAssets.getPluginAssetHref('/mongodb_logs/screenshot.webp'), onPrem: onPremInstructions(moduleName, platforms, context), elasticCloud: cloudInstructions(moduleName, platforms, context), onPremElasticCloud: onPremCloudInstructions(moduleName, platforms, context), diff --git a/src/plugins/home/server/tutorials/mongodb_metrics/index.ts b/src/plugins/home/server/tutorials/mongodb_metrics/index.ts index c4b56cef60d17..441ede88c5c38 100644 --- a/src/plugins/home/server/tutorials/mongodb_metrics/index.ts +++ b/src/plugins/home/server/tutorials/mongodb_metrics/index.ts @@ -57,7 +57,7 @@ export function mongodbMetricsSpecProvider(context: TutorialContext): TutorialSc }, }, completionTimeMinutes: 10, - previewImagePath: '/plugins/home/assets/mongodb_metrics/screenshot.webp', + previewImagePath: context.staticAssets.getPluginAssetHref('/mongodb_metrics/screenshot.webp'), onPrem: onPremInstructions(moduleName, context), elasticCloud: cloudInstructions(moduleName, context), onPremElasticCloud: onPremCloudInstructions(moduleName, context), diff --git a/src/plugins/home/server/tutorials/mssql_logs/index.ts b/src/plugins/home/server/tutorials/mssql_logs/index.ts index 2add9281860bd..ab8363afd25b6 100644 --- a/src/plugins/home/server/tutorials/mssql_logs/index.ts +++ b/src/plugins/home/server/tutorials/mssql_logs/index.ts @@ -39,7 +39,7 @@ export function mssqlLogsSpecProvider(context: TutorialContext): TutorialSchema learnMoreLink: '{config.docs.beats.filebeat}/filebeat-module-mssql.html', }, }), - euiIconType: '/plugins/home/assets/logos/microsoft.svg', + euiIconType: context.staticAssets.getPluginAssetHref('/logos/microsoft.svg'), artifacts: { dashboards: [], application: { diff --git a/src/plugins/home/server/tutorials/mssql_metrics/index.ts b/src/plugins/home/server/tutorials/mssql_metrics/index.ts index 5dd6bca41a812..33091b6b04504 100644 --- a/src/plugins/home/server/tutorials/mssql_metrics/index.ts +++ b/src/plugins/home/server/tutorials/mssql_metrics/index.ts @@ -38,7 +38,7 @@ export function mssqlMetricsSpecProvider(context: TutorialContext): TutorialSche learnMoreLink: '{config.docs.beats.metricbeat}/metricbeat-module-mssql.html', }, }), - euiIconType: '/plugins/home/assets/logos/mssql.svg', + euiIconType: context.staticAssets.getPluginAssetHref('/logos/mssql.svg'), isBeta: false, artifacts: { dashboards: [ @@ -55,7 +55,7 @@ export function mssqlMetricsSpecProvider(context: TutorialContext): TutorialSche }, }, completionTimeMinutes: 10, - previewImagePath: '/plugins/home/assets/mssql_metrics/screenshot.webp', + previewImagePath: context.staticAssets.getPluginAssetHref('/mssql_metrics/screenshot.webp'), onPrem: onPremInstructions(moduleName, context), elasticCloud: cloudInstructions(moduleName, context), onPremElasticCloud: onPremCloudInstructions(moduleName, context), diff --git a/src/plugins/home/server/tutorials/munin_metrics/index.ts b/src/plugins/home/server/tutorials/munin_metrics/index.ts index 1e3e091ab0b8e..aa9ba8e72ddd3 100644 --- a/src/plugins/home/server/tutorials/munin_metrics/index.ts +++ b/src/plugins/home/server/tutorials/munin_metrics/index.ts @@ -26,7 +26,7 @@ export function muninMetricsSpecProvider(context: TutorialContext): TutorialSche defaultMessage: 'Munin Metrics', }), moduleName, - euiIconType: '/plugins/home/assets/logos/munin.svg', + euiIconType: context.staticAssets.getPluginAssetHref('/logos/munin.svg'), isBeta: true, category: TutorialsCategory.METRICS, shortDescription: i18n.translate('home.tutorials.muninMetrics.shortDescription', { diff --git a/src/plugins/home/server/tutorials/mysql_logs/index.ts b/src/plugins/home/server/tutorials/mysql_logs/index.ts index 5ca657283d514..776926d9bd74d 100644 --- a/src/plugins/home/server/tutorials/mysql_logs/index.ts +++ b/src/plugins/home/server/tutorials/mysql_logs/index.ts @@ -55,7 +55,7 @@ export function mysqlLogsSpecProvider(context: TutorialContext): TutorialSchema }, }, completionTimeMinutes: 10, - previewImagePath: '/plugins/home/assets/mysql_logs/screenshot.webp', + previewImagePath: context.staticAssets.getPluginAssetHref('/mysql_logs/screenshot.webp'), onPrem: onPremInstructions(moduleName, platforms, context), elasticCloud: cloudInstructions(moduleName, platforms, context), onPremElasticCloud: onPremCloudInstructions(moduleName, platforms, context), diff --git a/src/plugins/home/server/tutorials/mysql_metrics/index.ts b/src/plugins/home/server/tutorials/mysql_metrics/index.ts index 8710fb70a4e2f..61f6d936f88e8 100644 --- a/src/plugins/home/server/tutorials/mysql_metrics/index.ts +++ b/src/plugins/home/server/tutorials/mysql_metrics/index.ts @@ -54,7 +54,7 @@ export function mysqlMetricsSpecProvider(context: TutorialContext): TutorialSche }, }, completionTimeMinutes: 10, - previewImagePath: '/plugins/home/assets/mysql_metrics/screenshot.webp', + previewImagePath: context.staticAssets.getPluginAssetHref('/mysql_metrics/screenshot.webp'), onPrem: onPremInstructions(moduleName, context), elasticCloud: cloudInstructions(moduleName, context), onPremElasticCloud: onPremCloudInstructions(moduleName, context), diff --git a/src/plugins/home/server/tutorials/nats_logs/index.ts b/src/plugins/home/server/tutorials/nats_logs/index.ts index d72a6df5e7104..2695edaf99380 100644 --- a/src/plugins/home/server/tutorials/nats_logs/index.ts +++ b/src/plugins/home/server/tutorials/nats_logs/index.ts @@ -40,7 +40,7 @@ export function natsLogsSpecProvider(context: TutorialContext): TutorialSchema { learnMoreLink: '{config.docs.beats.filebeat}/filebeat-module-nats.html', }, }), - euiIconType: '/plugins/home/assets/logos/nats.svg', + euiIconType: context.staticAssets.getPluginAssetHref('/logos/nats.svg'), artifacts: { dashboards: [ { @@ -56,7 +56,7 @@ export function natsLogsSpecProvider(context: TutorialContext): TutorialSchema { }, }, completionTimeMinutes: 10, - previewImagePath: '/plugins/home/assets/nats_logs/screenshot.webp', + previewImagePath: context.staticAssets.getPluginAssetHref('/nats_logs/screenshot.webp'), onPrem: onPremInstructions(moduleName, platforms, context), elasticCloud: cloudInstructions(moduleName, platforms, context), onPremElasticCloud: onPremCloudInstructions(moduleName, platforms, context), diff --git a/src/plugins/home/server/tutorials/nats_metrics/index.ts b/src/plugins/home/server/tutorials/nats_metrics/index.ts index 1aab107a61210..e9226331b5ec3 100644 --- a/src/plugins/home/server/tutorials/nats_metrics/index.ts +++ b/src/plugins/home/server/tutorials/nats_metrics/index.ts @@ -38,7 +38,7 @@ export function natsMetricsSpecProvider(context: TutorialContext): TutorialSchem learnMoreLink: '{config.docs.beats.metricbeat}/metricbeat-module-nats.html', }, }), - euiIconType: '/plugins/home/assets/logos/nats.svg', + euiIconType: context.staticAssets.getPluginAssetHref('/logos/nats.svg'), artifacts: { dashboards: [ { @@ -54,7 +54,7 @@ export function natsMetricsSpecProvider(context: TutorialContext): TutorialSchem }, }, completionTimeMinutes: 10, - previewImagePath: '/plugins/home/assets/nats_metrics/screenshot.webp', + previewImagePath: context.staticAssets.getPluginAssetHref('/nats_metrics/screenshot.webp'), onPrem: onPremInstructions(moduleName, context), elasticCloud: cloudInstructions(moduleName, context), onPremElasticCloud: onPremCloudInstructions(moduleName, context), diff --git a/src/plugins/home/server/tutorials/netscout_logs/index.ts b/src/plugins/home/server/tutorials/netscout_logs/index.ts index 9418a787be5d3..64e7fb351fff8 100644 --- a/src/plugins/home/server/tutorials/netscout_logs/index.ts +++ b/src/plugins/home/server/tutorials/netscout_logs/index.ts @@ -39,7 +39,7 @@ export function netscoutLogsSpecProvider(context: TutorialContext): TutorialSche learnMoreLink: '{config.docs.beats.filebeat}/filebeat-module-netscout.html', }, }), - euiIconType: '/plugins/home/assets/logos/netscout.svg', + euiIconType: context.staticAssets.getPluginAssetHref('/logos/netscout.svg'), artifacts: { dashboards: [], application: { diff --git a/src/plugins/home/server/tutorials/nginx_logs/index.ts b/src/plugins/home/server/tutorials/nginx_logs/index.ts index 451d1b8acbabb..5a08a6ebcddf4 100644 --- a/src/plugins/home/server/tutorials/nginx_logs/index.ts +++ b/src/plugins/home/server/tutorials/nginx_logs/index.ts @@ -55,7 +55,7 @@ export function nginxLogsSpecProvider(context: TutorialContext): TutorialSchema }, }, completionTimeMinutes: 10, - previewImagePath: '/plugins/home/assets/nginx_logs/screenshot.webp', + previewImagePath: context.staticAssets.getPluginAssetHref('/nginx_logs/screenshot.webp'), onPrem: onPremInstructions(moduleName, platforms, context), elasticCloud: cloudInstructions(moduleName, platforms, context), onPremElasticCloud: onPremCloudInstructions(moduleName, platforms, context), diff --git a/src/plugins/home/server/tutorials/nginx_metrics/index.ts b/src/plugins/home/server/tutorials/nginx_metrics/index.ts index 9441f59bbe56b..d133af96d03e0 100644 --- a/src/plugins/home/server/tutorials/nginx_metrics/index.ts +++ b/src/plugins/home/server/tutorials/nginx_metrics/index.ts @@ -59,7 +59,7 @@ which must be enabled in your Nginx installation. \ }, }, completionTimeMinutes: 10, - previewImagePath: '/plugins/home/assets/nginx_metrics/screenshot.webp', + previewImagePath: context.staticAssets.getPluginAssetHref('/nginx_metrics/screenshot.webp'), onPrem: onPremInstructions(moduleName, context), elasticCloud: cloudInstructions(moduleName, context), onPremElasticCloud: onPremCloudInstructions(moduleName, context), diff --git a/src/plugins/home/server/tutorials/o365_logs/index.ts b/src/plugins/home/server/tutorials/o365_logs/index.ts index c3cecbef32504..87dd8e7dcf246 100644 --- a/src/plugins/home/server/tutorials/o365_logs/index.ts +++ b/src/plugins/home/server/tutorials/o365_logs/index.ts @@ -42,7 +42,7 @@ export function o365LogsSpecProvider(context: TutorialContext): TutorialSchema { learnMoreLink: '{config.docs.beats.filebeat}/filebeat-module-o365.html', }, }), - euiIconType: '/plugins/home/assets/logos/o365.svg', + euiIconType: context.staticAssets.getPluginAssetHref('/logos/o365.svg'), artifacts: { dashboards: [ { @@ -58,7 +58,7 @@ export function o365LogsSpecProvider(context: TutorialContext): TutorialSchema { }, }, completionTimeMinutes: 10, - previewImagePath: '/plugins/home/assets/o365_logs/screenshot.webp', + previewImagePath: context.staticAssets.getPluginAssetHref('/o365_logs/screenshot.webp'), onPrem: onPremInstructions(moduleName, platforms, context), elasticCloud: cloudInstructions(moduleName, platforms, context), onPremElasticCloud: onPremCloudInstructions(moduleName, platforms, context), diff --git a/src/plugins/home/server/tutorials/okta_logs/index.ts b/src/plugins/home/server/tutorials/okta_logs/index.ts index c3929cff09099..4e4206ce95318 100644 --- a/src/plugins/home/server/tutorials/okta_logs/index.ts +++ b/src/plugins/home/server/tutorials/okta_logs/index.ts @@ -40,7 +40,7 @@ export function oktaLogsSpecProvider(context: TutorialContext): TutorialSchema { learnMoreLink: '{config.docs.beats.filebeat}/filebeat-module-okta.html', }, }), - euiIconType: '/plugins/home/assets/logos/okta.svg', + euiIconType: context.staticAssets.getPluginAssetHref('/logos/okta.svg'), artifacts: { dashboards: [ { @@ -56,7 +56,7 @@ export function oktaLogsSpecProvider(context: TutorialContext): TutorialSchema { }, }, completionTimeMinutes: 10, - previewImagePath: '/plugins/home/assets/okta_logs/screenshot.webp', + previewImagePath: context.staticAssets.getPluginAssetHref('/okta_logs/screenshot.webp'), onPrem: onPremInstructions(moduleName, platforms, context), elasticCloud: cloudInstructions(moduleName, platforms, context), onPremElasticCloud: onPremCloudInstructions(moduleName, platforms, context), diff --git a/src/plugins/home/server/tutorials/openmetrics_metrics/index.ts b/src/plugins/home/server/tutorials/openmetrics_metrics/index.ts index 9c0f6e89b6fa6..56db28fb0e9e2 100644 --- a/src/plugins/home/server/tutorials/openmetrics_metrics/index.ts +++ b/src/plugins/home/server/tutorials/openmetrics_metrics/index.ts @@ -39,7 +39,7 @@ export function openmetricsMetricsSpecProvider(context: TutorialContext): Tutori learnMoreLink: '{config.docs.beats.metricbeat}/metricbeat-module-openmetrics.html', }, }), - euiIconType: '/plugins/home/assets/logos/openmetrics.svg', + euiIconType: context.staticAssets.getPluginAssetHref('/logos/openmetrics.svg'), artifacts: { dashboards: [], exportedFields: { diff --git a/src/plugins/home/server/tutorials/oracle_metrics/index.ts b/src/plugins/home/server/tutorials/oracle_metrics/index.ts index 14f8dd0c39774..71cdedc6bb3ba 100644 --- a/src/plugins/home/server/tutorials/oracle_metrics/index.ts +++ b/src/plugins/home/server/tutorials/oracle_metrics/index.ts @@ -40,7 +40,7 @@ export function oracleMetricsSpecProvider(context: TutorialContext): TutorialSch learnMoreLink: '{config.docs.beats.metricbeat}/metricbeat-module-' + moduleName + '.html', }, }), - euiIconType: '/plugins/home/assets/logos/oracle.svg', + euiIconType: context.staticAssets.getPluginAssetHref('/logos/oracle.svg'), artifacts: { application: { label: i18n.translate('home.tutorials.oracleMetrics.artifacts.application.label', { diff --git a/src/plugins/home/server/tutorials/osquery_logs/index.ts b/src/plugins/home/server/tutorials/osquery_logs/index.ts index 8bf4ba94e9497..e73eb7e544df8 100644 --- a/src/plugins/home/server/tutorials/osquery_logs/index.ts +++ b/src/plugins/home/server/tutorials/osquery_logs/index.ts @@ -43,7 +43,7 @@ export function osqueryLogsSpecProvider(context: TutorialContext): TutorialSchem learnMoreLink: '{config.docs.beats.filebeat}/filebeat-module-osquery.html', }, }), - euiIconType: '/plugins/home/assets/logos/osquery.svg', + euiIconType: context.staticAssets.getPluginAssetHref('/logos/osquery.svg'), artifacts: { dashboards: [ { diff --git a/src/plugins/home/server/tutorials/panw_logs/index.ts b/src/plugins/home/server/tutorials/panw_logs/index.ts index 1279b0ebaf5a6..2aa4d6ebb6f2a 100644 --- a/src/plugins/home/server/tutorials/panw_logs/index.ts +++ b/src/plugins/home/server/tutorials/panw_logs/index.ts @@ -42,7 +42,7 @@ export function panwLogsSpecProvider(context: TutorialContext): TutorialSchema { learnMoreLink: '{config.docs.beats.filebeat}/filebeat-module-panw.html', }, }), - euiIconType: '/plugins/home/assets/logos/paloalto.svg', + euiIconType: context.staticAssets.getPluginAssetHref('/logos/paloalto.svg'), artifacts: { dashboards: [ { @@ -58,7 +58,7 @@ export function panwLogsSpecProvider(context: TutorialContext): TutorialSchema { }, }, completionTimeMinutes: 10, - previewImagePath: '/plugins/home/assets/panw_logs/screenshot.webp', + previewImagePath: context.staticAssets.getPluginAssetHref('/panw_logs/screenshot.webp'), onPrem: onPremInstructions(moduleName, platforms, context), elasticCloud: cloudInstructions(moduleName, platforms, context), onPremElasticCloud: onPremCloudInstructions(moduleName, platforms, context), diff --git a/src/plugins/home/server/tutorials/postgresql_logs/index.ts b/src/plugins/home/server/tutorials/postgresql_logs/index.ts index 0338d33d9851a..2f8d6acc10f93 100644 --- a/src/plugins/home/server/tutorials/postgresql_logs/index.ts +++ b/src/plugins/home/server/tutorials/postgresql_logs/index.ts @@ -58,7 +58,7 @@ export function postgresqlLogsSpecProvider(context: TutorialContext): TutorialSc }, }, completionTimeMinutes: 10, - previewImagePath: '/plugins/home/assets/postgresql_logs/screenshot.webp', + previewImagePath: context.staticAssets.getPluginAssetHref('/postgresql_logs/screenshot.webp'), onPrem: onPremInstructions(moduleName, platforms, context), elasticCloud: cloudInstructions(moduleName, platforms, context), onPremElasticCloud: onPremCloudInstructions(moduleName, platforms, context), diff --git a/src/plugins/home/server/tutorials/rabbitmq_logs/index.ts b/src/plugins/home/server/tutorials/rabbitmq_logs/index.ts index 49ca87b1fbaa0..5cfa4d9a7fedc 100644 --- a/src/plugins/home/server/tutorials/rabbitmq_logs/index.ts +++ b/src/plugins/home/server/tutorials/rabbitmq_logs/index.ts @@ -39,7 +39,7 @@ export function rabbitmqLogsSpecProvider(context: TutorialContext): TutorialSche learnMoreLink: '{config.docs.beats.filebeat}/filebeat-module-rabbitmq.html', }, }), - euiIconType: '/plugins/home/assets/logos/rabbitmq.svg', + euiIconType: context.staticAssets.getPluginAssetHref('/logos/rabbitmq.svg'), artifacts: { dashboards: [], application: { diff --git a/src/plugins/home/server/tutorials/rabbitmq_metrics/index.ts b/src/plugins/home/server/tutorials/rabbitmq_metrics/index.ts index 49b4abb6bf836..c3c955e4658a4 100644 --- a/src/plugins/home/server/tutorials/rabbitmq_metrics/index.ts +++ b/src/plugins/home/server/tutorials/rabbitmq_metrics/index.ts @@ -58,7 +58,7 @@ export function rabbitmqMetricsSpecProvider(context: TutorialContext): TutorialS }, }, completionTimeMinutes: 10, - previewImagePath: '/plugins/home/assets/rabbitmq_metrics/screenshot.webp', + previewImagePath: context.staticAssets.getPluginAssetHref('/rabbitmq_metrics/screenshot.webp'), onPrem: onPremInstructions(moduleName, context), elasticCloud: cloudInstructions(moduleName, context), onPremElasticCloud: onPremCloudInstructions(moduleName, context), diff --git a/src/plugins/home/server/tutorials/radware_logs/index.ts b/src/plugins/home/server/tutorials/radware_logs/index.ts index 4abd897c0aff3..607fe2fa60149 100644 --- a/src/plugins/home/server/tutorials/radware_logs/index.ts +++ b/src/plugins/home/server/tutorials/radware_logs/index.ts @@ -39,7 +39,7 @@ export function radwareLogsSpecProvider(context: TutorialContext): TutorialSchem learnMoreLink: '{config.docs.beats.filebeat}/filebeat-module-radware.html', }, }), - euiIconType: '/plugins/home/assets/logos/radware.svg', + euiIconType: context.staticAssets.getPluginAssetHref('/logos/radware.svg'), artifacts: { dashboards: [], application: { diff --git a/src/plugins/home/server/tutorials/redis_logs/index.ts b/src/plugins/home/server/tutorials/redis_logs/index.ts index f0110b1e4f360..5a278706f7530 100644 --- a/src/plugins/home/server/tutorials/redis_logs/index.ts +++ b/src/plugins/home/server/tutorials/redis_logs/index.ts @@ -61,7 +61,7 @@ Note that the `slowlog` fileset is experimental. \ }, }, completionTimeMinutes: 10, - previewImagePath: '/plugins/home/assets/redis_logs/screenshot.webp', + previewImagePath: context.staticAssets.getPluginAssetHref('/redis_logs/screenshot.webp'), onPrem: onPremInstructions(moduleName, platforms, context), elasticCloud: cloudInstructions(moduleName, platforms, context), onPremElasticCloud: onPremCloudInstructions(moduleName, platforms, context), diff --git a/src/plugins/home/server/tutorials/redis_metrics/index.ts b/src/plugins/home/server/tutorials/redis_metrics/index.ts index 1b541226ca24d..bef4dcf6b0778 100644 --- a/src/plugins/home/server/tutorials/redis_metrics/index.ts +++ b/src/plugins/home/server/tutorials/redis_metrics/index.ts @@ -54,7 +54,7 @@ export function redisMetricsSpecProvider(context: TutorialContext): TutorialSche }, }, completionTimeMinutes: 10, - previewImagePath: '/plugins/home/assets/redis_metrics/screenshot.webp', + previewImagePath: context.staticAssets.getPluginAssetHref('/redis_metrics/screenshot.webp'), onPrem: onPremInstructions(moduleName, context), elasticCloud: cloudInstructions(moduleName, context), onPremElasticCloud: onPremCloudInstructions(moduleName, context), diff --git a/src/plugins/home/server/tutorials/redisenterprise_metrics/index.ts b/src/plugins/home/server/tutorials/redisenterprise_metrics/index.ts index 608ce867727d3..fd1c26f4da16b 100644 --- a/src/plugins/home/server/tutorials/redisenterprise_metrics/index.ts +++ b/src/plugins/home/server/tutorials/redisenterprise_metrics/index.ts @@ -53,7 +53,9 @@ export function redisenterpriseMetricsSpecProvider(context: TutorialContext): Tu }, }, completionTimeMinutes: 10, - previewImagePath: '/plugins/home/assets/redisenterprise_metrics/screenshot.webp', + previewImagePath: context.staticAssets.getPluginAssetHref( + '/redisenterprise_metrics/screenshot.webp' + ), onPrem: onPremInstructions(moduleName, context), elasticCloud: cloudInstructions(moduleName, context), onPremElasticCloud: onPremCloudInstructions(moduleName, context), diff --git a/src/plugins/home/server/tutorials/santa_logs/index.ts b/src/plugins/home/server/tutorials/santa_logs/index.ts index eda644458ba3e..292c1b20c41d6 100644 --- a/src/plugins/home/server/tutorials/santa_logs/index.ts +++ b/src/plugins/home/server/tutorials/santa_logs/index.ts @@ -56,7 +56,7 @@ export function santaLogsSpecProvider(context: TutorialContext): TutorialSchema }, }, completionTimeMinutes: 10, - previewImagePath: '/plugins/home/assets/santa_logs/screenshot.webp', + previewImagePath: context.staticAssets.getPluginAssetHref('/santa_logs/screenshot.webp'), onPrem: onPremInstructions(moduleName, platforms, context), elasticCloud: cloudInstructions(moduleName, platforms, context), onPremElasticCloud: onPremCloudInstructions(moduleName, platforms, context), diff --git a/src/plugins/home/server/tutorials/sonicwall_logs/index.ts b/src/plugins/home/server/tutorials/sonicwall_logs/index.ts index 5e88eb03d75d2..00995b6767abf 100644 --- a/src/plugins/home/server/tutorials/sonicwall_logs/index.ts +++ b/src/plugins/home/server/tutorials/sonicwall_logs/index.ts @@ -39,7 +39,7 @@ export function sonicwallLogsSpecProvider(context: TutorialContext): TutorialSch learnMoreLink: '{config.docs.beats.filebeat}/filebeat-module-sonicwall.html', }, }), - euiIconType: '/plugins/home/assets/logos/sonicwall.svg', + euiIconType: context.staticAssets.getPluginAssetHref('/logos/sonicwall.svg'), artifacts: { dashboards: [], application: { diff --git a/src/plugins/home/server/tutorials/sophos_logs/index.ts b/src/plugins/home/server/tutorials/sophos_logs/index.ts index a504ae2a30802..5f43d0bccaf57 100644 --- a/src/plugins/home/server/tutorials/sophos_logs/index.ts +++ b/src/plugins/home/server/tutorials/sophos_logs/index.ts @@ -39,7 +39,7 @@ export function sophosLogsSpecProvider(context: TutorialContext): TutorialSchema learnMoreLink: '{config.docs.beats.filebeat}/filebeat-module-sophos.html', }, }), - euiIconType: '/plugins/home/assets/logos/sophos.svg', + euiIconType: context.staticAssets.getPluginAssetHref('/logos/sophos.svg'), artifacts: { dashboards: [], application: { diff --git a/src/plugins/home/server/tutorials/stan_metrics/index.ts b/src/plugins/home/server/tutorials/stan_metrics/index.ts index ca0be2097af13..c83b405e2058a 100644 --- a/src/plugins/home/server/tutorials/stan_metrics/index.ts +++ b/src/plugins/home/server/tutorials/stan_metrics/index.ts @@ -38,7 +38,7 @@ export function stanMetricsSpecProvider(context: TutorialContext): TutorialSchem learnMoreLink: '{config.docs.beats.metricbeat}/metricbeat-module-stan.html', }, }), - euiIconType: '/plugins/home/assets/logos/stan.svg', + euiIconType: context.staticAssets.getPluginAssetHref('/logos/stan.svg'), artifacts: { dashboards: [ { @@ -54,7 +54,7 @@ export function stanMetricsSpecProvider(context: TutorialContext): TutorialSchem }, }, completionTimeMinutes: 10, - previewImagePath: '/plugins/home/assets/stan_metrics/screenshot.webp', + previewImagePath: context.staticAssets.getPluginAssetHref('/stan_metrics/screenshot.webp'), onPrem: onPremInstructions(moduleName, context), elasticCloud: cloudInstructions(moduleName, context), onPremElasticCloud: onPremCloudInstructions(moduleName, context), diff --git a/src/plugins/home/server/tutorials/statsd_metrics/index.ts b/src/plugins/home/server/tutorials/statsd_metrics/index.ts index a7c8a27aa7afd..695c890bb449d 100644 --- a/src/plugins/home/server/tutorials/statsd_metrics/index.ts +++ b/src/plugins/home/server/tutorials/statsd_metrics/index.ts @@ -35,7 +35,7 @@ export function statsdMetricsSpecProvider(context: TutorialContext): TutorialSch learnMoreLink: '{config.docs.beats.metricbeat}/metricbeat-module-statsd.html', }, }), - euiIconType: '/plugins/home/assets/logos/statsd.svg', + euiIconType: context.staticAssets.getPluginAssetHref('/logos/statsd.svg'), artifacts: { dashboards: [], exportedFields: { diff --git a/src/plugins/home/server/tutorials/suricata_logs/index.ts b/src/plugins/home/server/tutorials/suricata_logs/index.ts index dfff18cd8f196..aa8a24a843c6d 100644 --- a/src/plugins/home/server/tutorials/suricata_logs/index.ts +++ b/src/plugins/home/server/tutorials/suricata_logs/index.ts @@ -40,7 +40,7 @@ export function suricataLogsSpecProvider(context: TutorialContext): TutorialSche learnMoreLink: '{config.docs.beats.filebeat}/filebeat-module-suricata.html', }, }), - euiIconType: '/plugins/home/assets/logos/suricata.svg', + euiIconType: context.staticAssets.getPluginAssetHref('/logos/suricata.svg'), artifacts: { dashboards: [ { @@ -56,7 +56,7 @@ export function suricataLogsSpecProvider(context: TutorialContext): TutorialSche }, }, completionTimeMinutes: 10, - previewImagePath: '/plugins/home/assets/suricata_logs/screenshot.webp', + previewImagePath: context.staticAssets.getPluginAssetHref('/suricata_logs/screenshot.webp'), onPrem: onPremInstructions(moduleName, platforms, context), elasticCloud: cloudInstructions(moduleName, platforms, context), onPremElasticCloud: onPremCloudInstructions(moduleName, platforms, context), diff --git a/src/plugins/home/server/tutorials/system_metrics/index.ts b/src/plugins/home/server/tutorials/system_metrics/index.ts index b9d607c9fc59c..1db7e1e335337 100644 --- a/src/plugins/home/server/tutorials/system_metrics/index.ts +++ b/src/plugins/home/server/tutorials/system_metrics/index.ts @@ -40,7 +40,7 @@ It collects system wide statistics and statistics per process and filesystem. \ learnMoreLink: '{config.docs.beats.metricbeat}/metricbeat-module-system.html', }, }), - euiIconType: '/plugins/home/assets/logos/system.svg', + euiIconType: context.staticAssets.getPluginAssetHref('/logos/system.svg'), artifacts: { dashboards: [ { @@ -56,7 +56,7 @@ It collects system wide statistics and statistics per process and filesystem. \ }, }, completionTimeMinutes: 10, - previewImagePath: '/plugins/home/assets/system_metrics/screenshot.webp', + previewImagePath: context.staticAssets.getPluginAssetHref('/system_metrics/screenshot.webp'), onPrem: onPremInstructions(moduleName, context), elasticCloud: cloudInstructions(moduleName, context), onPremElasticCloud: onPremCloudInstructions(moduleName, context), diff --git a/src/plugins/home/server/tutorials/tomcat_logs/index.ts b/src/plugins/home/server/tutorials/tomcat_logs/index.ts index 99198f835402c..6694f54428c99 100644 --- a/src/plugins/home/server/tutorials/tomcat_logs/index.ts +++ b/src/plugins/home/server/tutorials/tomcat_logs/index.ts @@ -39,7 +39,7 @@ export function tomcatLogsSpecProvider(context: TutorialContext): TutorialSchema learnMoreLink: '{config.docs.beats.filebeat}/filebeat-module-tomcat.html', }, }), - euiIconType: '/plugins/home/assets/logos/tomcat.svg', + euiIconType: context.staticAssets.getPluginAssetHref('/logos/tomcat.svg'), artifacts: { dashboards: [], application: { diff --git a/src/plugins/home/server/tutorials/traefik_logs/index.ts b/src/plugins/home/server/tutorials/traefik_logs/index.ts index 7c096f68aabfb..13a1c448c876a 100644 --- a/src/plugins/home/server/tutorials/traefik_logs/index.ts +++ b/src/plugins/home/server/tutorials/traefik_logs/index.ts @@ -39,7 +39,7 @@ export function traefikLogsSpecProvider(context: TutorialContext): TutorialSchem learnMoreLink: '{config.docs.beats.filebeat}/filebeat-module-traefik.html', }, }), - euiIconType: '/plugins/home/assets/logos/traefik.svg', + euiIconType: context.staticAssets.getPluginAssetHref('/logos/traefik.svg'), artifacts: { dashboards: [ { diff --git a/src/plugins/home/server/tutorials/traefik_metrics/index.ts b/src/plugins/home/server/tutorials/traefik_metrics/index.ts index 1bba0718fbd99..daa83e051bd28 100644 --- a/src/plugins/home/server/tutorials/traefik_metrics/index.ts +++ b/src/plugins/home/server/tutorials/traefik_metrics/index.ts @@ -35,7 +35,7 @@ export function traefikMetricsSpecProvider(context: TutorialContext): TutorialSc learnMoreLink: '{config.docs.beats.metricbeat}/metricbeat-module-traefik.html', }, }), - euiIconType: '/plugins/home/assets/logos/traefik.svg', + euiIconType: context.staticAssets.getPluginAssetHref('/logos/traefik.svg'), artifacts: { dashboards: [], exportedFields: { diff --git a/src/plugins/home/server/tutorials/uptime_monitors/index.ts b/src/plugins/home/server/tutorials/uptime_monitors/index.ts index 86b3e99e11057..653cf939108b3 100644 --- a/src/plugins/home/server/tutorials/uptime_monitors/index.ts +++ b/src/plugins/home/server/tutorials/uptime_monitors/index.ts @@ -53,7 +53,7 @@ export function uptimeMonitorsSpecProvider(context: TutorialContext): TutorialSc }, }, completionTimeMinutes: 10, - previewImagePath: '/plugins/home/assets/uptime_monitors/screenshot.webp', + previewImagePath: context.staticAssets.getPluginAssetHref('/uptime_monitors/screenshot.webp'), onPrem: onPremInstructions([], context), elasticCloud: cloudInstructions(context), onPremElasticCloud: onPremCloudInstructions(context), diff --git a/src/plugins/home/server/tutorials/uwsgi_metrics/index.ts b/src/plugins/home/server/tutorials/uwsgi_metrics/index.ts index 4fb6725255e0a..fedc37523baae 100644 --- a/src/plugins/home/server/tutorials/uwsgi_metrics/index.ts +++ b/src/plugins/home/server/tutorials/uwsgi_metrics/index.ts @@ -38,7 +38,7 @@ export function uwsgiMetricsSpecProvider(context: TutorialContext): TutorialSche learnMoreLink: '{config.docs.beats.metricbeat}/metricbeat-module-uwsgi.html', }, }), - euiIconType: '/plugins/home/assets/logos/uwsgi.svg', + euiIconType: context.staticAssets.getPluginAssetHref('/logos/uwsgi.svg'), isBeta: false, artifacts: { dashboards: [ @@ -55,7 +55,7 @@ export function uwsgiMetricsSpecProvider(context: TutorialContext): TutorialSche }, }, completionTimeMinutes: 10, - previewImagePath: '/plugins/home/assets/uwsgi_metrics/screenshot.webp', + previewImagePath: context.staticAssets.getPluginAssetHref('/uwsgi_metrics/screenshot.webp'), onPrem: onPremInstructions(moduleName, context), elasticCloud: cloudInstructions(moduleName, context), onPremElasticCloud: onPremCloudInstructions(moduleName, context), diff --git a/src/plugins/home/server/tutorials/vsphere_metrics/index.ts b/src/plugins/home/server/tutorials/vsphere_metrics/index.ts index 946da1b884a80..66359772a14c5 100644 --- a/src/plugins/home/server/tutorials/vsphere_metrics/index.ts +++ b/src/plugins/home/server/tutorials/vsphere_metrics/index.ts @@ -38,7 +38,7 @@ export function vSphereMetricsSpecProvider(context: TutorialContext): TutorialSc learnMoreLink: '{config.docs.beats.metricbeat}/metricbeat-module-vsphere.html', }, }), - euiIconType: '/plugins/home/assets/logos/vsphere.svg', + euiIconType: context.staticAssets.getPluginAssetHref('/logos/vsphere.svg'), isBeta: true, artifacts: { application: { diff --git a/src/plugins/home/server/tutorials/zeek_logs/index.ts b/src/plugins/home/server/tutorials/zeek_logs/index.ts index 387f1041f4974..1460fb6acf9b4 100644 --- a/src/plugins/home/server/tutorials/zeek_logs/index.ts +++ b/src/plugins/home/server/tutorials/zeek_logs/index.ts @@ -40,7 +40,7 @@ export function zeekLogsSpecProvider(context: TutorialContext): TutorialSchema { learnMoreLink: '{config.docs.beats.filebeat}/filebeat-module-zeek.html', }, }), - euiIconType: '/plugins/home/assets/logos/zeek.svg', + euiIconType: context.staticAssets.getPluginAssetHref('/logos/zeek.svg'), artifacts: { dashboards: [ { @@ -56,7 +56,7 @@ export function zeekLogsSpecProvider(context: TutorialContext): TutorialSchema { }, }, completionTimeMinutes: 10, - previewImagePath: '/plugins/home/assets/zeek_logs/screenshot.webp', + previewImagePath: context.staticAssets.getPluginAssetHref('/zeek_logs/screenshot.webp'), onPrem: onPremInstructions(moduleName, platforms, context), elasticCloud: cloudInstructions(moduleName, platforms, context), onPremElasticCloud: onPremCloudInstructions(moduleName, platforms, context), diff --git a/src/plugins/home/server/tutorials/zookeeper_metrics/index.ts b/src/plugins/home/server/tutorials/zookeeper_metrics/index.ts index dd65f61a78b3c..2479650a5198d 100644 --- a/src/plugins/home/server/tutorials/zookeeper_metrics/index.ts +++ b/src/plugins/home/server/tutorials/zookeeper_metrics/index.ts @@ -26,7 +26,7 @@ export function zookeeperMetricsSpecProvider(context: TutorialContext): Tutorial defaultMessage: 'Zookeeper Metrics', }), moduleName, - euiIconType: '/plugins/home/assets/logos/zookeeper.svg', + euiIconType: context.staticAssets.getPluginAssetHref('/logos/zookeeper.svg'), isBeta: false, category: TutorialsCategory.METRICS, shortDescription: i18n.translate('home.tutorials.zookeeperMetrics.shortDescription', { diff --git a/src/plugins/home/server/tutorials/zscaler_logs/index.ts b/src/plugins/home/server/tutorials/zscaler_logs/index.ts index 316590c74fd76..47be9df4cdf5c 100644 --- a/src/plugins/home/server/tutorials/zscaler_logs/index.ts +++ b/src/plugins/home/server/tutorials/zscaler_logs/index.ts @@ -39,7 +39,7 @@ export function zscalerLogsSpecProvider(context: TutorialContext): TutorialSchem learnMoreLink: '{config.docs.beats.filebeat}/filebeat-module-zscaler.html', }, }), - euiIconType: '/plugins/home/assets/logos/zscaler.svg', + euiIconType: context.staticAssets.getPluginAssetHref('/logos/zscaler.svg'), artifacts: { dashboards: [], application: { diff --git a/src/plugins/input_control_vis/server/index.ts b/src/plugins/input_control_vis/server/index.ts index 5054ac1ea2db5..46f04d5a4bbdf 100644 --- a/src/plugins/input_control_vis/server/index.ts +++ b/src/plugins/input_control_vis/server/index.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import { CoreSetup, PluginConfigDescriptor, PluginInitializerContext } from '@kbn/core/server'; +import type { CoreSetup, PluginConfigDescriptor, PluginInitializerContext } from '@kbn/core/server'; import type { VisualizationsServerSetup } from '@kbn/visualizations-plugin/server'; import { configSchema, InputControlConfig } from '../config'; @@ -22,7 +22,7 @@ interface PluginSetupDependencies { visualizations: VisualizationsServerSetup; } -export const plugin = (initializerContext: PluginInitializerContext) => ({ +export const plugin = async (initializerContext: PluginInitializerContext) => ({ setup(core: CoreSetup, plugins: PluginSetupDependencies) { const { readOnly } = initializerContext.config.get(); if (readOnly) { diff --git a/src/plugins/inspector/public/views/requests/components/details/clusters_view/clusters_view.tsx b/src/plugins/inspector/public/views/requests/components/details/clusters_view/clusters_view.tsx index 1e35e0276139e..8a96847832dc8 100644 --- a/src/plugins/inspector/public/views/requests/components/details/clusters_view/clusters_view.tsx +++ b/src/plugins/inspector/public/views/requests/components/details/clusters_view/clusters_view.tsx @@ -45,7 +45,7 @@ export class ClustersView extends Component { <> {Object.keys(clusters).length > 1 ? : null} - + ) : null; } diff --git a/src/plugins/interactive_setup/server/index.ts b/src/plugins/interactive_setup/server/index.ts index 885a4f4afa544..fc8c7fdd40b44 100644 --- a/src/plugins/interactive_setup/server/index.ts +++ b/src/plugins/interactive_setup/server/index.ts @@ -14,12 +14,14 @@ import type { } from '@kbn/core/server'; import { ConfigSchema } from './config'; -import { InteractiveSetupPlugin } from './plugin'; export const config: PluginConfigDescriptor> = { schema: ConfigSchema, }; -export const plugin: PluginInitializer = ( +export const plugin: PluginInitializer = async ( initializerContext: PluginInitializerContext -) => new InteractiveSetupPlugin(initializerContext); +) => { + const { InteractiveSetupPlugin } = await import('./plugin'); + return new InteractiveSetupPlugin(initializerContext); +}; diff --git a/src/plugins/kibana_react/public/index.ts b/src/plugins/kibana_react/public/index.ts index f665b5f4ee403..05abdbd84e91c 100644 --- a/src/plugins/kibana_react/public/index.ts +++ b/src/plugins/kibana_react/public/index.ts @@ -44,10 +44,6 @@ export { export { useExecutionContext } from './use_execution_context'; -export type { ToolbarButtonProps } from './toolbar_button'; -/** @deprecated ToolbarButton - use `ToolbarButton` from `@kbn/shared-ux-button-toolbar` */ -export { POSITIONS, WEIGHTS, TOOLBAR_BUTTON_SIZES, ToolbarButton } from './toolbar_button'; - export { reactRouterNavigate, reactRouterOnClickHandler } from './react_router_navigate'; export type { diff --git a/src/plugins/kibana_react/public/toolbar_button/__snapshots__/toolbar_button.test.tsx.snap b/src/plugins/kibana_react/public/toolbar_button/__snapshots__/toolbar_button.test.tsx.snap deleted file mode 100644 index 753dd8d6fe81f..0000000000000 --- a/src/plugins/kibana_react/public/toolbar_button/__snapshots__/toolbar_button.test.tsx.snap +++ /dev/null @@ -1,199 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`font weights bold is applied 1`] = ` - -`; - -exports[`font weights normal is applied 1`] = ` - -`; - -exports[`hasArrow is rendered 1`] = ` - -`; - -exports[`positions center is applied 1`] = ` - -`; - -exports[`positions left is applied 1`] = ` - -`; - -exports[`positions none is applied 1`] = ` - -`; - -exports[`positions right is applied 1`] = ` - -`; - -exports[`sizes m is applied 1`] = ` - -`; - -exports[`sizes s is applied 1`] = ` - -`; diff --git a/src/plugins/kibana_react/public/toolbar_button/toolbar_button.scss b/src/plugins/kibana_react/public/toolbar_button/toolbar_button.scss deleted file mode 100644 index cbf6d85349446..0000000000000 --- a/src/plugins/kibana_react/public/toolbar_button/toolbar_button.scss +++ /dev/null @@ -1,61 +0,0 @@ -.kbnToolbarButton { - line-height: $euiButtonHeight; // Keeps alignment of text and chart icon - - // Override background color for non-disabled buttons - &:not(:disabled) { - background-color: $euiColorEmptyShade; - } - - // todo: once issue https://github.com/elastic/eui/issues/4730 is merged, this code might be safe to remove - // Some toolbar buttons are just icons, but EuiButton comes with margin and min-width that need to be removed - min-width: 0; - border-width: $euiBorderWidthThin; - border-style: solid; - border-color: $euiBorderColor; // Lighten the border color for all states - - .kbnToolbarButton__text > svg { - margin-top: -1px; // Just some weird alignment issue when icon is the child not the `iconType` - } - - .kbnToolbarButton__text:empty { - margin: 0; - } - - // Toolbar buttons don't look good with centered text when fullWidth - &[class*='fullWidth'] { - text-align: left; - - .kbnToolbarButton__content { - justify-content: space-between; - } - } -} - -.kbnToolbarButton--groupLeft { - border-top-right-radius: 0; - border-bottom-right-radius: 0; -} - -.kbnToolbarButton--groupCenter { - border-radius: 0; - border-left: none; -} - -.kbnToolbarButton--groupRight { - border-top-left-radius: 0; - border-bottom-left-radius: 0; - border-left: none; -} - -.kbnToolbarButton--bold { - font-weight: $euiFontWeightBold; -} - -.kbnToolbarButton--normal { - font-weight: $euiFontWeightRegular; -} - -.kbnToolbarButton--s { - box-shadow: none !important; // sass-lint:disable-line no-important - font-size: $euiFontSizeS; -} diff --git a/src/plugins/kibana_react/public/toolbar_button/toolbar_button.test.tsx b/src/plugins/kibana_react/public/toolbar_button/toolbar_button.test.tsx deleted file mode 100644 index 97690e483393f..0000000000000 --- a/src/plugins/kibana_react/public/toolbar_button/toolbar_button.test.tsx +++ /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 and the Server Side Public License, v 1; you may 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 { shallow } from 'enzyme'; -import { ToolbarButton, POSITIONS, WEIGHTS, TOOLBAR_BUTTON_SIZES } from './toolbar_button'; - -const noop = () => {}; - -describe('sizes', () => { - TOOLBAR_BUTTON_SIZES.forEach((size) => { - test(`${size} is applied`, () => { - const component = shallow(); - expect(component).toMatchSnapshot(); - }); - }); -}); - -describe('positions', () => { - POSITIONS.forEach((position) => { - test(`${position} is applied`, () => { - const component = shallow(); - expect(component).toMatchSnapshot(); - }); - }); -}); - -describe('font weights', () => { - WEIGHTS.forEach((weight) => { - test(`${weight} is applied`, () => { - const component = shallow(); - expect(component).toMatchSnapshot(); - }); - }); -}); - -describe('hasArrow', () => { - it('is rendered', () => { - const component = shallow(); - expect(component).toMatchSnapshot(); - }); -}); diff --git a/src/plugins/kibana_react/public/toolbar_button/toolbar_button.tsx b/src/plugins/kibana_react/public/toolbar_button/toolbar_button.tsx deleted file mode 100644 index 4b22710eef795..0000000000000 --- a/src/plugins/kibana_react/public/toolbar_button/toolbar_button.tsx +++ /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 and the Server Side Public License, v 1; you may 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 './toolbar_button.scss'; -import React from 'react'; -import classNames from 'classnames'; -import { EuiButton, PropsOf, EuiButtonProps } from '@elastic/eui'; - -const groupPositionToClassMap = { - none: null, - left: 'kbnToolbarButton--groupLeft', - center: 'kbnToolbarButton--groupCenter', - right: 'kbnToolbarButton--groupRight', -}; - -type ButtonPositions = keyof typeof groupPositionToClassMap; -export const POSITIONS = Object.keys(groupPositionToClassMap) as ButtonPositions[]; - -type Weights = 'normal' | 'bold'; -export const WEIGHTS = ['normal', 'bold'] as Weights[]; - -export const TOOLBAR_BUTTON_SIZES: Array = ['s', 'm']; - -export type ToolbarButtonProps = PropsOf & { - /** - * Determines prominence - */ - fontWeight?: Weights; - /** - * Smaller buttons also remove extra shadow for less prominence - */ - size?: EuiButtonProps['size']; - /** - * Determines if the button will have a down arrow or not - */ - hasArrow?: boolean; - /** - * Adjusts the borders for groupings - */ - groupPosition?: ButtonPositions; - dataTestSubj?: string; -}; - -export const ToolbarButton: React.FunctionComponent = ({ - children, - className, - fontWeight = 'normal', - size = 'm', - hasArrow = true, - groupPosition = 'none', - dataTestSubj = '', - ...rest -}) => { - const classes = classNames( - 'kbnToolbarButton', - groupPositionToClassMap[groupPosition], - [`kbnToolbarButton--${fontWeight}`, `kbnToolbarButton--${size}`], - className - ); - - return ( - - {children} - - ); -}; diff --git a/src/plugins/kibana_usage_collection/server/collectors/saved_objects_counts/get_saved_object_counts/get_saved_object_counts.test.ts b/src/plugins/kibana_usage_collection/server/collectors/saved_objects_counts/get_saved_object_counts/get_saved_object_counts.test.ts index f83200f56f27c..c21b922f4142f 100644 --- a/src/plugins/kibana_usage_collection/server/collectors/saved_objects_counts/get_saved_object_counts/get_saved_object_counts.test.ts +++ b/src/plugins/kibana_usage_collection/server/collectors/saved_objects_counts/get_saved_object_counts/get_saved_object_counts.test.ts @@ -34,6 +34,7 @@ describe('getSavedObjectsCounts', () => { await getSavedObjectsCounts(soClient, ['type-a', 'type_2']); expect(soClient.find).toHaveBeenCalledWith({ type: ['type-a', 'type_2'], + namespaces: ['*'], perPage: 0, aggs: { types: { @@ -49,9 +50,10 @@ describe('getSavedObjectsCounts', () => { test('should apply the terms query and aggregation with the size matching the length of the list when `exclusive === true`', async () => { soClient.find.mockResolvedValueOnce(soEmptyResponse); - await getSavedObjectsCounts(soClient, ['type_one', 'type_two'], true); + await getSavedObjectsCounts(soClient, ['type_one', 'type_two'], { exclusive: true }); expect(soClient.find).toHaveBeenCalledWith({ type: ['type_one', 'type_two'], + namespaces: ['*'], perPage: 0, aggs: { types: { terms: { field: 'type', size: 2 } } }, }); diff --git a/src/plugins/kibana_usage_collection/server/collectors/saved_objects_counts/get_saved_object_counts/get_saved_object_counts.ts b/src/plugins/kibana_usage_collection/server/collectors/saved_objects_counts/get_saved_object_counts/get_saved_object_counts.ts index cdca68e5d6006..d062d3c35b328 100644 --- a/src/plugins/kibana_usage_collection/server/collectors/saved_objects_counts/get_saved_object_counts/get_saved_object_counts.ts +++ b/src/plugins/kibana_usage_collection/server/collectors/saved_objects_counts/get_saved_object_counts/get_saved_object_counts.ts @@ -41,17 +41,24 @@ export interface SavedObjectsCounts { * * @param soClient The {@link SavedObjectsClientContract} to use when performing the aggregation. * @param soTypes The SO types we want to know about. - * @param exclusive If `true`, the results will only contain the breakdown for the specified `soTypes`. Otherwise, it'll also return `missing` and `others` bucket. + * @param options.exclusive If `true`, the results will only contain the breakdown for the specified `soTypes`. Otherwise, it'll also return `missing` and `others` bucket. + * @param options.namespaces array of namespaces to search. Otherwise it'll default to all namespaces ['*']. * @returns {@link SavedObjectsCounts} */ export async function getSavedObjectsCounts( soClient: SavedObjectsClientContract, soTypes: string[], - exclusive: boolean = false + options?: { + exclusive?: boolean; + namespaces?: string[]; + } ): Promise { + const { exclusive = false, namespaces = ['*'] } = options || {}; + const body = await soClient.find({ type: soTypes, perPage: 0, + namespaces, aggs: { types: { terms: { diff --git a/src/plugins/kibana_usage_collection/server/collectors/saved_objects_counts/kibana_usage_collector.test.ts b/src/plugins/kibana_usage_collection/server/collectors/saved_objects_counts/kibana_usage_collector.test.ts index 7d6e600ded94b..831bc5a700a00 100644 --- a/src/plugins/kibana_usage_collection/server/collectors/saved_objects_counts/kibana_usage_collector.test.ts +++ b/src/plugins/kibana_usage_collection/server/collectors/saved_objects_counts/kibana_usage_collector.test.ts @@ -97,7 +97,7 @@ describe('getKibanaSavedObjectCounts', () => { expect(getSavedObjectsCountsMock).toHaveBeenCalledWith( soClient, ['dashboard', 'visualization', 'search', 'index-pattern', 'graph-workspace'], - true + { exclusive: true } ); }); }); diff --git a/src/plugins/kibana_usage_collection/server/collectors/saved_objects_counts/kibana_usage_collector.ts b/src/plugins/kibana_usage_collection/server/collectors/saved_objects_counts/kibana_usage_collector.ts index 8451b3eadeb00..17b8666f9fb83 100644 --- a/src/plugins/kibana_usage_collection/server/collectors/saved_objects_counts/kibana_usage_collector.ts +++ b/src/plugins/kibana_usage_collection/server/collectors/saved_objects_counts/kibana_usage_collector.ts @@ -28,7 +28,7 @@ const TYPES = ['dashboard', 'visualization', 'search', 'index-pattern', 'graph-w export async function getKibanaSavedObjectCounts( soClient: SavedObjectsClientContract ): Promise { - const { per_type: buckets } = await getSavedObjectsCounts(soClient, TYPES, true); + const { per_type: buckets } = await getSavedObjectsCounts(soClient, TYPES, { exclusive: true }); const allZeros = Object.fromEntries( TYPES.map((type) => [snakeCase(type), { total: 0 }]) diff --git a/src/plugins/kibana_usage_collection/server/collectors/saved_objects_counts/saved_objects_count_collector.test.ts b/src/plugins/kibana_usage_collection/server/collectors/saved_objects_counts/saved_objects_count_collector.test.ts index 53168be3c34b6..dbce4a5765441 100644 --- a/src/plugins/kibana_usage_collection/server/collectors/saved_objects_counts/saved_objects_count_collector.test.ts +++ b/src/plugins/kibana_usage_collection/server/collectors/saved_objects_counts/saved_objects_count_collector.test.ts @@ -16,15 +16,21 @@ import { registerSavedObjectsCountUsageCollector } from './saved_objects_count_c describe('saved_objects_count_collector', () => { const usageCollectionMock = createUsageCollectionSetupMock(); const fetchContextMock = createCollectorFetchContextMock(); + const mockGetSoClientWithHiddenIndices = jest.fn().mockResolvedValue(fetchContextMock.soClient); beforeAll(() => - registerSavedObjectsCountUsageCollector(usageCollectionMock, () => - Promise.resolve(['type_one', 'type_two', 'type-three', 'type-four']) + registerSavedObjectsCountUsageCollector( + usageCollectionMock, + () => Promise.resolve(['type_one', 'type_two', 'type-three', 'type-four']), + mockGetSoClientWithHiddenIndices ) ); afterAll(() => jest.clearAllTimers()); - afterEach(() => getSavedObjectsCountsMock.mockReset()); + afterEach(() => { + getSavedObjectsCountsMock.mockReset(); + mockGetSoClientWithHiddenIndices.mockClear(); + }); test('registered collector is set', () => { expect(usageCollectionMock.makeUsageCollector).toHaveBeenCalled(); @@ -48,6 +54,8 @@ describe('saved_objects_count_collector', () => { non_registered_types: [], others: 0, }); + + expect(mockGetSoClientWithHiddenIndices).toBeCalledTimes(1); }); test('should return some values when the aggregations return something', async () => { @@ -78,10 +86,11 @@ describe('saved_objects_count_collector', () => { total: 153, }); + expect(mockGetSoClientWithHiddenIndices).toBeCalledTimes(1); expect(getSavedObjectsCountsMock).toHaveBeenCalledWith( fetchContextMock.soClient, ['type_one', 'type_two', 'type-three', 'type-four'], - false + { exclusive: false, namespaces: ['*'] } ); }); }); diff --git a/src/plugins/kibana_usage_collection/server/collectors/saved_objects_counts/saved_objects_count_collector.ts b/src/plugins/kibana_usage_collection/server/collectors/saved_objects_counts/saved_objects_count_collector.ts index 49bfb7819389d..b327c3d591731 100644 --- a/src/plugins/kibana_usage_collection/server/collectors/saved_objects_counts/saved_objects_count_collector.ts +++ b/src/plugins/kibana_usage_collection/server/collectors/saved_objects_counts/saved_objects_count_collector.ts @@ -6,6 +6,7 @@ * Side Public License, v 1. */ +import { SavedObjectsClientContract } from '@kbn/core-saved-objects-api-server'; import type { UsageCollectionSetup } from '@kbn/usage-collection-plugin/server'; import { getSavedObjectsCounts } from './get_saved_object_counts'; @@ -23,7 +24,8 @@ interface SavedObjectsCountUsage { export function registerSavedObjectsCountUsageCollector( usageCollection: UsageCollectionSetup, - getAllSavedObjectTypes: () => Promise + getAllSavedObjectTypes: () => Promise, + getSoClientWithHiddenIndices: () => Promise ) { usageCollection.registerCollector( usageCollection.makeUsageCollector({ @@ -67,14 +69,19 @@ export function registerSavedObjectsCountUsageCollector( }, }, }, - async fetch({ soClient }) { + async fetch() { + const soClient = await getSoClientWithHiddenIndices(); const allRegisteredSOTypes = await getAllSavedObjectTypes(); + const namespaces = ['*']; const { total, per_type: buckets, non_expected_types: nonRegisteredTypes, others, - } = await getSavedObjectsCounts(soClient, allRegisteredSOTypes, false); + } = await getSavedObjectsCounts(soClient, allRegisteredSOTypes, { + namespaces, + exclusive: false, + }); return { total, by_type: buckets.map(({ key: type, doc_count: count }) => ({ type, count })), diff --git a/src/plugins/kibana_usage_collection/server/index.ts b/src/plugins/kibana_usage_collection/server/index.ts index 2a674035ebe29..0b6b06559c2d2 100644 --- a/src/plugins/kibana_usage_collection/server/index.ts +++ b/src/plugins/kibana_usage_collection/server/index.ts @@ -7,11 +7,11 @@ */ import { PluginInitializerContext } from '@kbn/core/server'; -import { KibanaUsageCollectionPlugin } from './plugin'; // This exports static code and TypeScript types, // as well as, Kibana Platform `plugin()` initializer. -export function plugin(initializerContext: PluginInitializerContext) { +export async function plugin(initializerContext: PluginInitializerContext) { + const { KibanaUsageCollectionPlugin } = await import('./plugin'); return new KibanaUsageCollectionPlugin(initializerContext); } diff --git a/src/plugins/kibana_usage_collection/server/plugin.test.ts b/src/plugins/kibana_usage_collection/server/plugin.test.ts index ef26492c2d6fd..a798eaa5aa1df 100644 --- a/src/plugins/kibana_usage_collection/server/plugin.test.ts +++ b/src/plugins/kibana_usage_collection/server/plugin.test.ts @@ -17,9 +17,10 @@ import { } from '@kbn/usage-collection-plugin/server/mocks'; import { cloudDetailsMock, registerEbtCountersMock } from './plugin.test.mocks'; import { plugin } from '.'; +import type { KibanaUsageCollectionPlugin } from './plugin'; describe('kibana_usage_collection', () => { - const pluginInstance = plugin(coreMock.createPluginInitializerContext({})); + let pluginInstance: KibanaUsageCollectionPlugin; const usageCollectors: CollectorOptions[] = []; @@ -33,6 +34,10 @@ describe('kibana_usage_collection', () => { return createUsageCollectionSetupMock().makeStatsCollector(opts); }); + beforeAll(async () => { + pluginInstance = await plugin(coreMock.createPluginInitializerContext({})); + }); + beforeEach(() => { cloudDetailsMock.mockClear(); }); diff --git a/src/plugins/kibana_usage_collection/server/plugin.ts b/src/plugins/kibana_usage_collection/server/plugin.ts index 5c807e01c0ce0..ff38116c1de44 100644 --- a/src/plugins/kibana_usage_collection/server/plugin.ts +++ b/src/plugins/kibana_usage_collection/server/plugin.ts @@ -152,7 +152,19 @@ export class KibanaUsageCollectionPlugin implements Plugin { .getAllTypes() .map(({ name }) => name); }; - registerSavedObjectsCountUsageCollector(usageCollection, getAllSavedObjectTypes); + + const getSoClientWithHiddenIndices = async () => { + const coreStart = await coreStartPromise; + + const allSoTypes = await getAllSavedObjectTypes(); + return coreStart.savedObjects.createInternalRepository(allSoTypes); + }; + + registerSavedObjectsCountUsageCollector( + usageCollection, + getAllSavedObjectTypes, + getSoClientWithHiddenIndices + ); registerManagementUsageCollector(usageCollection, getUiSettingsClient); registerUiMetricUsageCollector(usageCollection, registerType, getSavedObjectsClient); registerApplicationUsageCollector( diff --git a/src/plugins/links/server/index.ts b/src/plugins/links/server/index.ts index c60d084fa66d2..37ef2afdcb555 100644 --- a/src/plugins/links/server/index.ts +++ b/src/plugins/links/server/index.ts @@ -7,6 +7,8 @@ */ import { PluginInitializerContext } from '@kbn/core-plugins-server'; -import { LinksServerPlugin } from './plugin'; -export const plugin = (initContext: PluginInitializerContext) => new LinksServerPlugin(initContext); +export const plugin = async (initContext: PluginInitializerContext) => { + const { LinksServerPlugin } = await import('./plugin'); + return new LinksServerPlugin(initContext); +}; diff --git a/src/plugins/management/server/index.ts b/src/plugins/management/server/index.ts index 5d8ddf53fd068..5a0ee0a457dec 100644 --- a/src/plugins/management/server/index.ts +++ b/src/plugins/management/server/index.ts @@ -7,8 +7,9 @@ */ import { PluginInitializerContext } from '@kbn/core/server'; -import { ManagementServerPlugin } from './plugin'; export { config } from './config'; -export const plugin = (initContext: PluginInitializerContext) => - new ManagementServerPlugin(initContext); +export const plugin = async (initContext: PluginInitializerContext) => { + const { ManagementServerPlugin } = await import('./plugin'); + return new ManagementServerPlugin(initContext); +}; diff --git a/src/plugins/maps_ems/server/index.ts b/src/plugins/maps_ems/server/index.ts index a0a5cd6c7e72e..0fea54b0ba974 100644 --- a/src/plugins/maps_ems/server/index.ts +++ b/src/plugins/maps_ems/server/index.ts @@ -6,17 +6,10 @@ * Side Public License, v 1. */ -import { - CoreSetup, - PluginInitializerContext, - Plugin, - PluginConfigDescriptor, -} from '@kbn/core/server'; -import { LicensingPluginSetup } from '@kbn/licensing-plugin/server'; -import { ILicense } from '@kbn/licensing-plugin/common/types'; +import { PluginInitializerContext, PluginConfigDescriptor } from '@kbn/core/server'; import { MapConfig, mapConfigSchema } from '../config'; -import { EMSSettings, LICENSE_CHECK_ID } from '../common'; export type { EMSSettings } from '../common'; +export type { MapsEmsPluginServerSetup } from './plugin'; export const config: PluginConfigDescriptor = { exposeToBrowser: { @@ -32,48 +25,7 @@ export const config: PluginConfigDescriptor = { schema: mapConfigSchema, }; -export interface MapsEmsPluginServerSetup { - config: MapConfig; - createEMSSettings: () => EMSSettings; -} - -interface MapsEmsSetupServerDependencies { - licensing?: LicensingPluginSetup; -} - -export class MapsEmsPlugin implements Plugin { - readonly _initializerContext: PluginInitializerContext; - - constructor(initializerContext: PluginInitializerContext) { - this._initializerContext = initializerContext; - } - - public setup(core: CoreSetup, plugins: MapsEmsSetupServerDependencies) { - const mapConfig = this._initializerContext.config.get(); - - let isEnterprisePlus = false; - if (plugins.licensing) { - function updateLicenseState(license: ILicense) { - const enterprise = license.check(LICENSE_CHECK_ID, 'enterprise'); - isEnterprisePlus = enterprise.state === 'valid'; - } - - plugins.licensing.refresh().then(updateLicenseState); - plugins.licensing.license$.subscribe(updateLicenseState); - } - - return { - config: mapConfig, - createEMSSettings: () => { - return new EMSSettings(mapConfig, () => { - return isEnterprisePlus; - }); - }, - }; - } - - public start() {} -} - -export const plugin = (initializerContext: PluginInitializerContext) => - new MapsEmsPlugin(initializerContext); +export const plugin = async (initializerContext: PluginInitializerContext) => { + const { MapsEmsPlugin } = await import('./plugin'); + return new MapsEmsPlugin(initializerContext); +}; diff --git a/src/plugins/maps_ems/server/plugin.ts b/src/plugins/maps_ems/server/plugin.ts new file mode 100644 index 0000000000000..ebdc6814fd6eb --- /dev/null +++ b/src/plugins/maps_ems/server/plugin.ts @@ -0,0 +1,56 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { ILicense, LicensingPluginSetup } from '@kbn/licensing-plugin/server'; +import { Plugin, PluginInitializerContext } from '@kbn/core-plugins-server'; +import { CoreSetup } from '@kbn/core-lifecycle-server'; +import { MapConfig } from '../config'; +import { LICENSE_CHECK_ID, EMSSettings } from '../common'; + +export interface MapsEmsPluginServerSetup { + config: MapConfig; + createEMSSettings: () => EMSSettings; +} + +interface MapsEmsSetupServerDependencies { + licensing?: LicensingPluginSetup; +} + +export class MapsEmsPlugin implements Plugin { + readonly _initializerContext: PluginInitializerContext; + + constructor(initializerContext: PluginInitializerContext) { + this._initializerContext = initializerContext; + } + + public setup(core: CoreSetup, plugins: MapsEmsSetupServerDependencies) { + const mapConfig = this._initializerContext.config.get(); + + let isEnterprisePlus = false; + if (plugins.licensing) { + function updateLicenseState(license: ILicense) { + const enterprise = license.check(LICENSE_CHECK_ID, 'enterprise'); + isEnterprisePlus = enterprise.state === 'valid'; + } + + plugins.licensing.refresh().then(updateLicenseState); + plugins.licensing.license$.subscribe(updateLicenseState); + } + + return { + config: mapConfig, + createEMSSettings: () => { + return new EMSSettings(mapConfig, () => { + return isEnterprisePlus; + }); + }, + }; + } + + public start() {} +} diff --git a/src/plugins/maps_ems/tsconfig.json b/src/plugins/maps_ems/tsconfig.json index 7d32dacb6d55a..e8ed41cf54f36 100644 --- a/src/plugins/maps_ems/tsconfig.json +++ b/src/plugins/maps_ems/tsconfig.json @@ -11,6 +11,8 @@ "@kbn/config-schema", "@kbn/config", "@kbn/core-http-common", + "@kbn/core-plugins-server", + "@kbn/core-lifecycle-server", ], "exclude": [ "target/**/*", diff --git a/src/plugins/newsfeed/server/index.ts b/src/plugins/newsfeed/server/index.ts index 60df08a9b95e1..fe3acbeb40dac 100644 --- a/src/plugins/newsfeed/server/index.ts +++ b/src/plugins/newsfeed/server/index.ts @@ -7,7 +7,6 @@ */ import { PluginConfigDescriptor } from '@kbn/core/server'; -import { NewsfeedPlugin } from './plugin'; import { configSchema, NewsfeedConfigType } from './config'; export const config: PluginConfigDescriptor = { @@ -19,6 +18,7 @@ export const config: PluginConfigDescriptor = { }, }; -export function plugin() { +export async function plugin() { + const { NewsfeedPlugin } = await import('./plugin'); return new NewsfeedPlugin(); } diff --git a/src/plugins/presentation_util/public/components/dashboard_picker/dashboard_picker.tsx b/src/plugins/presentation_util/public/components/dashboard_picker/dashboard_picker.tsx index b2d8a576ebae8..01b1c8d2210da 100644 --- a/src/plugins/presentation_util/public/components/dashboard_picker/dashboard_picker.tsx +++ b/src/plugins/presentation_util/public/components/dashboard_picker/dashboard_picker.tsx @@ -20,7 +20,7 @@ import { EuiHighlight, } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; -import { ToolbarButton } from '@kbn/kibana-react-plugin/public'; +import { ToolbarButton } from '@kbn/shared-ux-button-toolbar'; import { SavedObjectCommon } from '@kbn/saved-objects-finder-plugin/common'; import { pluginServices } from '../../services'; @@ -122,19 +122,20 @@ export function DashboardPicker({ isDisabled, onChange, idsToOmit }: DashboardPi isLoading={isLoading} data-test-subj="open-dashboard-picker" onClick={() => setIsPopoverOpen(!isPopoverOpen)} - > - - {selectedDashboard?.label ?? - i18n.translate('presentationUtil.dashboardPicker.noDashboardOptionLabel', { - defaultMessage: 'Select dashboard', - })} - - + label={ + + {selectedDashboard?.label ?? + i18n.translate('presentationUtil.dashboardPicker.noDashboardOptionLabel', { + defaultMessage: 'Select dashboard', + })} + + } + /> } isOpen={isPopoverOpen} closePopover={() => setIsPopoverOpen(false)} diff --git a/src/plugins/presentation_util/public/components/data_view_picker/data_view_picker.tsx b/src/plugins/presentation_util/public/components/data_view_picker/data_view_picker.tsx index a7ee475cfa5d3..1804a2fcf2046 100644 --- a/src/plugins/presentation_util/public/components/data_view_picker/data_view_picker.tsx +++ b/src/plugins/presentation_util/public/components/data_view_picker/data_view_picker.tsx @@ -10,9 +10,9 @@ import React, { useState } from 'react'; import { EuiSelectable, EuiInputPopover, EuiSelectableProps } from '@elastic/eui'; import { DataViewListItem } from '@kbn/data-views-plugin/common'; -import { ToolbarButton, ToolbarButtonProps } from '@kbn/kibana-react-plugin/public'; +import { ToolbarButton, ToolbarButtonProps } from '@kbn/shared-ux-button-toolbar'; -export type DataViewTriggerProps = ToolbarButtonProps & { +export type DataViewTriggerProps = Omit, 'label'> & { label: string; title?: string; }; @@ -46,15 +46,14 @@ export function DataViewPicker({ const { label, title, ...rest } = trigger; return ( setPopoverIsOpen(!isPopoverOpen)} + label={label} fullWidth {...colorProp} {...rest} - > - {label} - + /> ); }; diff --git a/src/plugins/presentation_util/server/index.ts b/src/plugins/presentation_util/server/index.ts index d1f9ef6da760a..dad4ef0e8362e 100644 --- a/src/plugins/presentation_util/server/index.ts +++ b/src/plugins/presentation_util/server/index.ts @@ -6,7 +6,8 @@ * Side Public License, v 1. */ -import { PresentationUtilPlugin } from './plugin'; - export { SETTING_CATEGORY } from './ui_settings'; -export const plugin = () => new PresentationUtilPlugin(); +export const plugin = async () => { + const { PresentationUtilPlugin } = await import('./plugin'); + return new PresentationUtilPlugin(); +}; diff --git a/src/plugins/presentation_util/tsconfig.json b/src/plugins/presentation_util/tsconfig.json index 1270c0802dff2..e17fd6cc5a754 100644 --- a/src/plugins/presentation_util/tsconfig.json +++ b/src/plugins/presentation_util/tsconfig.json @@ -30,7 +30,8 @@ "@kbn/storybook", "@kbn/ui-actions-plugin", "@kbn/saved-objects-finder-plugin", - "@kbn/content-management-plugin" + "@kbn/content-management-plugin", + "@kbn/shared-ux-button-toolbar" ], "exclude": ["target/**/*"] } diff --git a/src/plugins/saved_objects_finder/server/index.ts b/src/plugins/saved_objects_finder/server/index.ts index 5d73b4387c9ff..fb5abfd46f7d9 100644 --- a/src/plugins/saved_objects_finder/server/index.ts +++ b/src/plugins/saved_objects_finder/server/index.ts @@ -6,6 +6,7 @@ * Side Public License, v 1. */ -import { SavedObjectsServerPlugin } from './plugin'; - -export const plugin = () => new SavedObjectsServerPlugin(); +export const plugin = async () => { + const { SavedObjectsServerPlugin } = await import('./plugin'); + return new SavedObjectsServerPlugin(); +}; diff --git a/src/plugins/saved_objects_management/public/management_section/object_view/__snapshots__/saved_object_view.test.tsx.snap b/src/plugins/saved_objects_management/public/management_section/object_view/__snapshots__/saved_object_view.test.tsx.snap index a04790ca6af23..538755e8d677d 100644 --- a/src/plugins/saved_objects_management/public/management_section/object_view/__snapshots__/saved_object_view.test.tsx.snap +++ b/src/plugins/saved_objects_management/public/management_section/object_view/__snapshots__/saved_object_view.test.tsx.snap @@ -17,6 +17,7 @@ exports[`SavedObjectEdition should render normally 1`] = ` "isOverridden": [MockFunction], "remove": [MockFunction], "set": [MockFunction], + "validateValue": [MockFunction], }, "globalClient": Object { "get": [MockFunction], @@ -30,6 +31,7 @@ exports[`SavedObjectEdition should render normally 1`] = ` "isOverridden": [MockFunction], "remove": [MockFunction], "set": [MockFunction], + "validateValue": [MockFunction], }, }, "theme": Object { @@ -49,6 +51,7 @@ exports[`SavedObjectEdition should render normally 1`] = ` "isOverridden": [MockFunction], "remove": [MockFunction], "set": [MockFunction], + "validateValue": [MockFunction], }, } } diff --git a/src/plugins/saved_objects_management/public/management_section/objects_table/__snapshots__/saved_objects_table.test.tsx.snap b/src/plugins/saved_objects_management/public/management_section/objects_table/__snapshots__/saved_objects_table.test.tsx.snap index 1a2fdf031a9d3..92bae41b22e58 100644 --- a/src/plugins/saved_objects_management/public/management_section/objects_table/__snapshots__/saved_objects_table.test.tsx.snap +++ b/src/plugins/saved_objects_management/public/management_section/objects_table/__snapshots__/saved_objects_table.test.tsx.snap @@ -188,6 +188,7 @@ exports[`SavedObjectsTable should render normally 1`] = ` } basePath={ BasePath { + "assetsHrefBase": "", "basePath": "", "get": [Function], "prepend": [Function], diff --git a/src/plugins/saved_objects_management/public/management_section/objects_table/components/__snapshots__/flyout.test.tsx.snap b/src/plugins/saved_objects_management/public/management_section/objects_table/components/__snapshots__/flyout.test.tsx.snap index 7d4ed131f6eac..03ba5cf5d9ead 100644 --- a/src/plugins/saved_objects_management/public/management_section/objects_table/components/__snapshots__/flyout.test.tsx.snap +++ b/src/plugins/saved_objects_management/public/management_section/objects_table/components/__snapshots__/flyout.test.tsx.snap @@ -174,6 +174,7 @@ exports[`Flyout conflicts should allow conflict resolution 2`] = ` "register": [MockFunction], }, "basePath": BasePath { + "assetsHrefBase": "", "basePath": "", "get": [Function], "prepend": [Function], @@ -195,6 +196,9 @@ exports[`Flyout conflicts should allow conflict resolution 2`] = ` "patch": [MockFunction], "post": [MockFunction], "put": [MockFunction], + "staticAssets": Object { + "getPluginAssetHref": [MockFunction], + }, }, "state": Object { "conflictingRecord": undefined, @@ -401,6 +405,7 @@ exports[`Flyout summary should display summary when import is complete 1`] = ` allowedTypes={Array []} basePath={ BasePath { + "assetsHrefBase": "", "basePath": "", "get": [Function], "prepend": [Function], diff --git a/src/plugins/saved_objects_management/public/management_section/objects_table/components/table.tsx b/src/plugins/saved_objects_management/public/management_section/objects_table/components/table.tsx index 3e0352f613d7e..79e4d32643108 100644 --- a/src/plugins/saved_objects_management/public/management_section/objects_table/components/table.tsx +++ b/src/plugins/saved_objects_management/public/management_section/objects_table/components/table.tsx @@ -13,7 +13,7 @@ import { EuiSearchBar, EuiBasicTable, EuiButton, - EuiIcon, + EuiIconTip, EuiLink, EuiSpacer, EuiToolTip, @@ -245,14 +245,13 @@ export class Table extends PureComponent { render: (type: string, object: SavedObjectWithMetadata) => { const typeLabel = getSavedObjectLabel(type, allowedTypes); return ( - - - + ); }, } as EuiTableFieldDataColumnType>, diff --git a/src/plugins/saved_objects_management/server/index.ts b/src/plugins/saved_objects_management/server/index.ts index 1ec0db16fd62b..e602a0fdae0f3 100644 --- a/src/plugins/saved_objects_management/server/index.ts +++ b/src/plugins/saved_objects_management/server/index.ts @@ -7,10 +7,11 @@ */ import { PluginInitializerContext } from '@kbn/core/server'; -import { SavedObjectsManagementPlugin } from './plugin'; -export const plugin = (context: PluginInitializerContext) => - new SavedObjectsManagementPlugin(context); +export const plugin = async (context: PluginInitializerContext) => { + const { SavedObjectsManagementPlugin } = await import('./plugin'); + return new SavedObjectsManagementPlugin(context); +}; export type { SavedObjectsManagementPluginSetup, diff --git a/src/plugins/saved_search/server/index.ts b/src/plugins/saved_search/server/index.ts index 056de3732b474..6c08bad317b9c 100644 --- a/src/plugins/saved_search/server/index.ts +++ b/src/plugins/saved_search/server/index.ts @@ -7,9 +7,10 @@ */ import type { PluginInitializerContext } from '@kbn/core-plugins-server'; -import { SavedSearchServerPlugin } from './plugin'; export { getSavedSearch } from './services/saved_searches'; -export const plugin = (initContext: PluginInitializerContext) => - new SavedSearchServerPlugin(initContext); +export const plugin = async (initContext: PluginInitializerContext) => { + const { SavedSearchServerPlugin } = await import('./plugin'); + return new SavedSearchServerPlugin(initContext); +}; diff --git a/src/plugins/screenshot_mode/server/index.ts b/src/plugins/screenshot_mode/server/index.ts index cc5d45b7be732..55dfd3967f4e4 100644 --- a/src/plugins/screenshot_mode/server/index.ts +++ b/src/plugins/screenshot_mode/server/index.ts @@ -6,8 +6,6 @@ * Side Public License, v 1. */ -import { ScreenshotModePlugin } from './plugin'; - export { setScreenshotModeEnabled, KBN_SCREENSHOT_MODE_HEADER, @@ -20,6 +18,7 @@ export type { ScreenshotModePluginStart, } from './types'; -export function plugin() { +export async function plugin() { + const { ScreenshotModePlugin } = await import('./plugin'); return new ScreenshotModePlugin(); } diff --git a/src/plugins/share/server/index.ts b/src/plugins/share/server/index.ts index c55d91d053b50..d38575a3b7cd4 100644 --- a/src/plugins/share/server/index.ts +++ b/src/plugins/share/server/index.ts @@ -7,12 +7,12 @@ */ import { PluginInitializerContext } from '@kbn/core/server'; -import { SharePlugin } from './plugin'; export type { SharePluginSetup, SharePluginStart } from './plugin'; export { CSV_QUOTE_VALUES_SETTING, CSV_SEPARATOR_SETTING } from '../common/constants'; -export function plugin(initializerContext: PluginInitializerContext) { +export async function plugin(initializerContext: PluginInitializerContext) { + const { SharePlugin } = await import('./plugin'); return new SharePlugin(initializerContext); } diff --git a/src/plugins/telemetry/server/index.ts b/src/plugins/telemetry/server/index.ts index 3c67764953ef4..85096e763259b 100644 --- a/src/plugins/telemetry/server/index.ts +++ b/src/plugins/telemetry/server/index.ts @@ -8,13 +8,14 @@ import type { PluginInitializerContext } from '@kbn/core/server'; import type { TelemetryConfigType } from './config'; -import { TelemetryPlugin } from './plugin'; export { config } from './config'; export type { TelemetryPluginSetup, TelemetryPluginStart } from './plugin'; -export const plugin = (initializerContext: PluginInitializerContext) => - new TelemetryPlugin(initializerContext); +export const plugin = async (initializerContext: PluginInitializerContext) => { + const { TelemetryPlugin } = await import('./plugin'); + return new TelemetryPlugin(initializerContext); +}; export { getClusterUuids, getLocalStats } from './telemetry_collection'; export type { diff --git a/src/plugins/telemetry_collection_manager/server/index.ts b/src/plugins/telemetry_collection_manager/server/index.ts index ededc6abb87dd..d588a18b4e91f 100644 --- a/src/plugins/telemetry_collection_manager/server/index.ts +++ b/src/plugins/telemetry_collection_manager/server/index.ts @@ -7,12 +7,12 @@ */ import { PluginInitializerContext } from '@kbn/core/server'; -import { TelemetryCollectionManagerPlugin } from './plugin'; // This exports static code and TypeScript types, // as well as, Kibana Platform `plugin()` initializer. -export function plugin(initializerContext: PluginInitializerContext) { +export async function plugin(initializerContext: PluginInitializerContext) { + const { TelemetryCollectionManagerPlugin } = await import('./plugin'); return new TelemetryCollectionManagerPlugin(initializerContext); } diff --git a/src/plugins/telemetry_management_section/public/components/__snapshots__/telemetry_management_section.test.tsx.snap b/src/plugins/telemetry_management_section/public/components/__snapshots__/telemetry_management_section.test.tsx.snap index 515add8c29dd4..430cf538779b6 100644 --- a/src/plugins/telemetry_management_section/public/components/__snapshots__/telemetry_management_section.test.tsx.snap +++ b/src/plugins/telemetry_management_section/public/components/__snapshots__/telemetry_management_section.test.tsx.snap @@ -281,6 +281,7 @@ exports[`TelemetryManagementSectionComponent renders null because allowChangingO "register": [MockFunction], }, "basePath": BasePath { + "assetsHrefBase": "", "basePath": "", "get": [Function], "prepend": [Function], @@ -302,6 +303,9 @@ exports[`TelemetryManagementSectionComponent renders null because allowChangingO "patch": [MockFunction], "post": [MockFunction], "put": [MockFunction], + "staticAssets": Object { + "getPluginAssetHref": [MockFunction], + }, }, "isScreenshotMode": false, "notifications": Object { diff --git a/src/plugins/ui_actions_enhanced/server/index.ts b/src/plugins/ui_actions_enhanced/server/index.ts index 04df6d4b1e841..bb62e2b86a19c 100644 --- a/src/plugins/ui_actions_enhanced/server/index.ts +++ b/src/plugins/ui_actions_enhanced/server/index.ts @@ -6,14 +6,13 @@ * Side Public License, v 1. */ -import { AdvancedUiActionsServerPlugin } from './plugin'; - -export function plugin() { +export async function plugin() { + const { AdvancedUiActionsServerPlugin } = await import('./plugin'); return new AdvancedUiActionsServerPlugin(); } -export { AdvancedUiActionsServerPlugin as Plugin }; export type { + AdvancedUiActionsServerPlugin as Plugin, SetupContract as AdvancedUiActionsSetup, StartContract as AdvancedUiActionsStart, } from './plugin'; diff --git a/src/plugins/unified_search/public/filter_badge/filter_badge.tsx b/src/plugins/unified_search/public/filter_badge/filter_badge.tsx index c1cc5c7a3da56..7b20eab971e9c 100644 --- a/src/plugins/unified_search/public/filter_badge/filter_badge.tsx +++ b/src/plugins/unified_search/public/filter_badge/filter_badge.tsx @@ -63,6 +63,7 @@ function FilterBadge({ diff --git a/src/plugins/unified_search/public/filter_bar/filter_editor/filter_editor.tsx b/src/plugins/unified_search/public/filter_bar/filter_editor/filter_editor.tsx index fb3acc3daa54c..f6d539aadfe18 100644 --- a/src/plugins/unified_search/public/filter_bar/filter_editor/filter_editor.tsx +++ b/src/plugins/unified_search/public/filter_bar/filter_editor/filter_editor.tsx @@ -56,7 +56,11 @@ import { } from './lib/filter_editor_utils'; import { FiltersBuilder } from '../../filters_builder'; import { FilterBadgeGroup } from '../../filter_badge/filter_badge_group'; -import { flattenFilters } from './lib/helpers'; +import { + MIDDLE_TRUNCATION_PROPS, + SINGLE_SELECTION_AS_TEXT_PROPS, + flattenFilters, +} from './lib/helpers'; import { filterBadgeStyle, filterPreviewLabelStyle, @@ -301,9 +305,10 @@ class FilterEditorComponent extends Component { selectedOptions={selectedDataView ? [selectedDataView] : []} getLabel={(indexPattern) => indexPattern.getName()} onChange={this.onIndexPatternChange} - singleSelection={{ asPlainText: true }} isClearable={false} data-test-subj="filterIndexPatternsSelect" + singleSelection={SINGLE_SELECTION_AS_TEXT_PROPS} + truncationProps={MIDDLE_TRUNCATION_PROPS} /> @@ -371,7 +376,7 @@ class FilterEditorComponent extends Component { } > - + { OPTION_CONTENT_CLASSNAME: string ) => React.ReactNode; inputRef?: ((instance: HTMLInputElement | null) => void) | undefined; + truncationProps?: EuiComboBoxProps['truncationProps']; [propName: string]: any; } diff --git a/src/plugins/unified_search/public/filter_bar/filter_editor/index.ts b/src/plugins/unified_search/public/filter_bar/filter_editor/index.ts index f1ff6c50b5787..4192f415770bc 100644 --- a/src/plugins/unified_search/public/filter_bar/filter_editor/index.ts +++ b/src/plugins/unified_search/public/filter_bar/filter_editor/index.ts @@ -36,7 +36,6 @@ export { PhrasesValuesInput } from './phrases_values_input'; export { PhraseValueInput } from './phrase_value_input'; export { RangeValueInput, isRangeParams } from './range_value_input'; export { ValueInputType } from './value_input_type'; -export { TruncatedLabel } from './truncated_label'; export { FilterEditor } from './filter_editor'; export type { FilterEditorProps } from './filter_editor'; diff --git a/src/plugins/unified_search/public/filter_bar/filter_editor/lib/helpers.ts b/src/plugins/unified_search/public/filter_bar/filter_editor/lib/helpers.ts index 53c36525e1d35..31c5c5a9656e3 100644 --- a/src/plugins/unified_search/public/filter_bar/filter_editor/lib/helpers.ts +++ b/src/plugins/unified_search/public/filter_bar/filter_editor/lib/helpers.ts @@ -63,3 +63,6 @@ export const flattenFilters = (filter: Filter[]) => { return returnArray; }; + +export const MIDDLE_TRUNCATION_PROPS = { truncation: 'middle' as const }; +export const SINGLE_SELECTION_AS_TEXT_PROPS = { asPlainText: true }; diff --git a/src/plugins/unified_search/public/filter_bar/filter_editor/phrase_value_input.tsx b/src/plugins/unified_search/public/filter_bar/filter_editor/phrase_value_input.tsx index 0a466c61770ce..62648ae50d26a 100644 --- a/src/plugins/unified_search/public/filter_bar/filter_editor/phrase_value_input.tsx +++ b/src/plugins/unified_search/public/filter_bar/filter_editor/phrase_value_input.tsx @@ -10,11 +10,10 @@ import { InjectedIntl, injectI18n } from '@kbn/i18n-react'; import { uniq } from 'lodash'; import React from 'react'; import { withKibana } from '@kbn/kibana-react-plugin/public'; -import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; import { GenericComboBox, GenericComboBoxProps } from './generic_combo_box'; import { PhraseSuggestorUI, PhraseSuggestorProps } from './phrase_suggestor'; import { ValueInputType } from './value_input_type'; -import { TruncatedLabel } from './truncated_label'; +import { MIDDLE_TRUNCATION_PROPS, SINGLE_SELECTION_AS_TEXT_PROPS } from './lib/helpers'; interface PhraseValueInputProps extends PhraseSuggestorProps { value?: string; @@ -26,10 +25,6 @@ interface PhraseValueInputProps extends PhraseSuggestorProps { invalid?: boolean; } -const DEFAULT_COMBOBOX_WIDTH = 250; -const COMBOBOX_PADDINGS = 10; -const DEFAULT_FONT = '14px Inter'; - class PhraseValueInputUI extends PhraseSuggestorUI { comboBoxWrapperRef = React.createRef(); inputRef: HTMLInputElement | null = null; @@ -92,24 +87,11 @@ class PhraseValueInputUI extends PhraseSuggestorUI { }); }} onSearchChange={this.onSearchChange} - singleSelection={{ asPlainText: true }} onCreateOption={onChange} isClearable={false} data-test-subj="filterParamsComboBox phraseParamsComboxBox" - renderOption={(option, searchValue) => ( - - - - - - )} + singleSelection={SINGLE_SELECTION_AS_TEXT_PROPS} + truncationProps={MIDDLE_TRUNCATION_PROPS} />
); diff --git a/src/plugins/unified_search/public/filter_bar/filter_editor/phrases_values_input.tsx b/src/plugins/unified_search/public/filter_bar/filter_editor/phrases_values_input.tsx index b31e6aad7d438..513dad1445823 100644 --- a/src/plugins/unified_search/public/filter_bar/filter_editor/phrases_values_input.tsx +++ b/src/plugins/unified_search/public/filter_bar/filter_editor/phrases_values_input.tsx @@ -10,11 +10,11 @@ import { InjectedIntl, injectI18n } from '@kbn/i18n-react'; import { uniq } from 'lodash'; import React from 'react'; import { withKibana } from '@kbn/kibana-react-plugin/public'; -import { EuiFlexGroup, EuiFlexItem, withEuiTheme, WithEuiThemeProps } from '@elastic/eui'; +import { withEuiTheme, WithEuiThemeProps } from '@elastic/eui'; import { GenericComboBox, GenericComboBoxProps } from './generic_combo_box'; import { PhraseSuggestorUI, PhraseSuggestorProps } from './phrase_suggestor'; -import { TruncatedLabel } from './truncated_label'; import { phrasesValuesComboboxCss } from './phrases_values_input.styles'; +import { MIDDLE_TRUNCATION_PROPS } from './lib/helpers'; interface Props { values?: string[]; @@ -27,11 +27,6 @@ interface Props { } export type PhrasesValuesInputProps = Props & PhraseSuggestorProps & WithEuiThemeProps; - -const DEFAULT_COMBOBOX_WIDTH = 250; -const COMBOBOX_PADDINGS = 20; -const DEFAULT_FONT = '14px Inter'; - class PhrasesValuesInputUI extends PhraseSuggestorUI { comboBoxWrapperRef = React.createRef(); @@ -67,20 +62,7 @@ class PhrasesValuesInputUI extends PhraseSuggestorUI { isClearable={false} data-test-subj="filterParamsComboBox phrasesParamsComboxBox" isDisabled={disabled} - renderOption={(option, searchValue) => ( - - - - - - )} + truncationProps={MIDDLE_TRUNCATION_PROPS} />
); diff --git a/src/plugins/unified_search/public/filter_bar/filter_editor/truncated_label.test.tsx b/src/plugins/unified_search/public/filter_bar/filter_editor/truncated_label.test.tsx deleted file mode 100644 index 08236041ab93a..0000000000000 --- a/src/plugins/unified_search/public/filter_bar/filter_editor/truncated_label.test.tsx +++ /dev/null @@ -1,79 +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, { ComponentProps } from 'react'; -import { mount } from 'enzyme'; -import { TruncatedLabel } from './truncated_label'; - -describe('truncated_label', () => { - const defaultProps: ComponentProps = { - defaultFont: '14px Inter', - defaultComboboxWidth: 130, - comboboxPaddings: 100, - comboBoxWrapperRef: React.createRef(), - search: '', - label: 'example_field', - }; - it('displays passed label if shorter than passed labelLength', () => { - const wrapper = mount(); - expect(wrapper.text()).toEqual('example_field'); - }); - it('middle truncates label', () => { - const wrapper = mount( - - ); - expect(wrapper.text()).toEqual('example_….subcategory.subfield'); - }); - describe('with search value passed', () => { - it('constructs truncated label when searching for the string of index = 0', () => { - const wrapper = mount( - - ); - expect(wrapper.text()).toEqual('example_space.example_field.s…'); - expect(wrapper.find('mark').text()).toEqual('example_space'); - }); - it('constructs truncated label when searching for the string in the middle', () => { - const wrapper = mount( - - ); - expect(wrapper.text()).toEqual('…ample_field.subcategory.subf…'); - expect(wrapper.find('mark').text()).toEqual('ample_field'); - }); - it('constructs truncated label when searching for the string at the end of the label', () => { - const wrapper = mount( - - ); - expect(wrapper.text()).toEqual('…le_field.subcategory.subfield'); - expect(wrapper.find('mark').text()).toEqual('subf'); - }); - - it('constructs truncated label when searching for the string longer than the truncated width and highlights the whole content', () => { - const wrapper = mount( - - ); - expect(wrapper.text()).toEqual('…ample_space.example_field.su…'); - expect(wrapper.find('mark').text()).toEqual('…ample_space.example_field.su…'); - }); - }); -}); diff --git a/src/plugins/unified_search/public/filter_bar/filter_editor/truncated_label.tsx b/src/plugins/unified_search/public/filter_bar/filter_editor/truncated_label.tsx deleted file mode 100644 index 21304ad244edf..0000000000000 --- a/src/plugins/unified_search/public/filter_bar/filter_editor/truncated_label.tsx +++ /dev/null @@ -1,141 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may 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, { RefObject, useMemo } from 'react'; -import useEffectOnce from 'react-use/lib/useEffectOnce'; -import { EuiMark } from '@elastic/eui'; -import { EuiHighlight } from '@elastic/eui'; -import { throttle } from 'lodash'; - -interface TruncatedLabelProps { - label: string; - search: string; - comboBoxWrapperRef: RefObject; - defaultFont: string; - defaultComboboxWidth: number; - comboboxPaddings: number; -} - -const createContext = () => - document.createElement('canvas').getContext('2d') as CanvasRenderingContext2D; - -// extracted from getTextWidth for performance -const context = createContext(); - -const getTextWidth = (text: string, font: string) => { - const ctx = context ?? createContext(); - ctx.font = font; - const metrics = ctx.measureText(text); - return metrics.width; -}; - -const truncateLabel = ( - width: number, - font: string, - label: string, - approximateLength: number, - labelFn: (label: string, length: number) => string -) => { - let output = labelFn(label, approximateLength); - - while (getTextWidth(output, font) > width) { - approximateLength = approximateLength - 1; - const newOutput = labelFn(label, approximateLength); - if (newOutput === output) { - break; - } - output = newOutput; - } - return output; -}; - -export const TruncatedLabel = React.memo(function TruncatedLabel({ - label, - comboBoxWrapperRef, - search, - defaultFont, - defaultComboboxWidth, - comboboxPaddings, -}: TruncatedLabelProps) { - const [labelProps, setLabelProps] = React.useState<{ - width: number; - font: string; - }>({ - width: defaultComboboxWidth - comboboxPaddings, - font: defaultFont, - }); - const computeStyles = (_e: UIEvent | undefined, shouldRecomputeAll = false) => { - if (comboBoxWrapperRef.current) { - const current = { - ...labelProps, - width: comboBoxWrapperRef.current.clientWidth - comboboxPaddings, - }; - if (shouldRecomputeAll) { - current.font = window.getComputedStyle(comboBoxWrapperRef.current).font; - } - setLabelProps(current); - } - }; - - const handleResize = throttle((_e: UIEvent | undefined, shouldRecomputeAll = false) => { - computeStyles(_e, shouldRecomputeAll); - }, 50); - - useEffectOnce(() => { - if (comboBoxWrapperRef.current) { - handleResize(undefined, true); - } - - window.addEventListener('resize', handleResize); - return () => { - window.removeEventListener('resize', handleResize); - }; - }); - - const textWidth = useMemo(() => getTextWidth(label, labelProps.font), [label, labelProps.font]); - - if (textWidth < labelProps.width) { - return {label}; - } - - const searchPosition = label.indexOf(search); - const approximateLen = Math.round((labelProps.width * label.length) / textWidth); - const separator = `…`; - let separatorsLength = separator.length; - let labelFn; - - if (!search || searchPosition === -1) { - labelFn = (text: string, length: number) => - `${text.substr(0, 8)}${separator}${text.substr(text.length - (length - 8))}`; - } else if (searchPosition === 0) { - // search phrase at the beginning - labelFn = (text: string, length: number) => `${text.substr(0, length)}${separator}`; - } else if (approximateLen > label.length - searchPosition) { - // search phrase close to the end or at the end - labelFn = (text: string, length: number) => `${separator}${text.substr(text.length - length)}`; - } else { - // search phrase is in the middle - labelFn = (text: string, length: number) => - `${separator}${text.substr(searchPosition, length)}${separator}`; - separatorsLength = 2 * separator.length; - } - - const outputLabel = truncateLabel( - labelProps.width, - labelProps.font, - label, - approximateLen, - labelFn - ); - - return search.length < outputLabel.length - separatorsLength ? ( - {outputLabel} - ) : ( - {outputLabel} - ); -}); diff --git a/src/plugins/unified_search/public/filter_bar/filter_item/filter_item.tsx b/src/plugins/unified_search/public/filter_bar/filter_item/filter_item.tsx index 9c25c7eaf06e8..d14891c5fc3ff 100644 --- a/src/plugins/unified_search/public/filter_bar/filter_item/filter_item.tsx +++ b/src/plugins/unified_search/public/filter_bar/filter_item/filter_item.tsx @@ -80,7 +80,7 @@ export type FilterLabelStatus = | typeof FILTER_ITEM_WARNING | typeof FILTER_ITEM_ERROR; -export const FILTER_EDITOR_WIDTH = 960; +export const FILTER_EDITOR_WIDTH = 1200; function FilterItemComponent(props: FilterItemProps) { const { onCloseFilterPopover, onLocalFilterCreate, onLocalFilterUpdate } = props; diff --git a/src/plugins/unified_search/public/filters_builder/filter_item/field_input.tsx b/src/plugins/unified_search/public/filters_builder/filter_item/field_input.tsx index 8c3dc65758c29..540226caef525 100644 --- a/src/plugins/unified_search/public/filters_builder/filter_item/field_input.tsx +++ b/src/plugins/unified_search/public/filters_builder/filter_item/field_input.tsx @@ -11,20 +11,13 @@ import { i18n } from '@kbn/i18n'; import { FieldIcon } from '@kbn/react-field'; import { KBN_FIELD_TYPES } from '@kbn/field-types'; import type { DataView, DataViewField } from '@kbn/data-views-plugin/common'; -import { - EuiFlexGroup, - EuiFlexItem, - useGeneratedHtmlId, - EuiComboBox, - EuiComboBoxOptionOption, -} from '@elastic/eui'; +import { useGeneratedHtmlId, EuiComboBox, EuiComboBoxOptionOption } from '@elastic/eui'; import { getFilterableFields } from '../../filter_bar/filter_editor'; import { FiltersBuilderContextType } from '../context'; -import { TruncatedLabel } from '../../filter_bar/filter_editor'; - -const DEFAULT_COMBOBOX_WIDTH = 205; -const COMBOBOX_PADDINGS = 100; -const DEFAULT_FONT = '14px Inter'; +import { + MIDDLE_TRUNCATION_PROPS, + SINGLE_SELECTION_AS_TEXT_PROPS, +} from '../../filter_bar/filter_editor/lib/helpers'; export const strings = { getFieldSelectPlaceholderLabel: () => @@ -62,6 +55,7 @@ export function FieldInput({ field, dataView, onHandleField }: FieldInputProps) return { label, value: dataViewField.type as KBN_FIELD_TYPES, + prepend: , }; }, [suggestionsAbstraction] @@ -103,30 +97,14 @@ export function FieldInput({ field, dataView, onHandleField }: FieldInputProps) isDisabled={disabled} placeholder={strings.getFieldSelectPlaceholderLabel()} sortMatchesBy="startsWith" - singleSelection={{ asPlainText: true }} aria-label={strings.getFieldSelectPlaceholderLabel()} isClearable={false} compressed fullWidth onFocus={handleFocus} data-test-subj="filterFieldSuggestionList" - renderOption={(option, searchValue) => ( - - - - - - - - - )} + singleSelection={SINGLE_SELECTION_AS_TEXT_PROPS} + truncationProps={MIDDLE_TRUNCATION_PROPS} /> ); diff --git a/src/plugins/unified_search/server/index.ts b/src/plugins/unified_search/server/index.ts index d1948f32e2fe9..8f786e0ed1077 100644 --- a/src/plugins/unified_search/server/index.ts +++ b/src/plugins/unified_search/server/index.ts @@ -8,7 +8,7 @@ import { PluginConfigDescriptor, PluginInitializerContext } from '@kbn/core/server'; import { ConfigSchema, configSchema } from '../config'; -import { +import type { UnifiedSearchServerPlugin, UnifiedSearchServerPluginSetup, UnifiedSearchServerPluginStart, @@ -21,7 +21,8 @@ import { autocompleteConfigDeprecationProvider } from './config_deprecations'; * @public */ -export function plugin(initializerContext: PluginInitializerContext) { +export async function plugin(initializerContext: PluginInitializerContext) { + const { UnifiedSearchServerPlugin } = await import('./plugin'); return new UnifiedSearchServerPlugin(initializerContext); } @@ -29,7 +30,7 @@ export type { UnifiedSearchServerPluginSetup as PluginSetup, UnifiedSearchServerPluginStart as PluginStart, }; -export { UnifiedSearchServerPlugin as Plugin }; +export type { UnifiedSearchServerPlugin as Plugin }; export const config: PluginConfigDescriptor = { deprecations: autocompleteConfigDeprecationProvider, diff --git a/src/plugins/usage_collection/server/index.ts b/src/plugins/usage_collection/server/index.ts index 7e66b1bd323b0..38298b42ed9c1 100644 --- a/src/plugins/usage_collection/server/index.ts +++ b/src/plugins/usage_collection/server/index.ts @@ -7,7 +7,6 @@ */ import { PluginInitializerContext } from '@kbn/core/server'; -import { UsageCollectionPlugin } from './plugin'; export type { Collector, @@ -31,5 +30,7 @@ export { USAGE_COUNTERS_SAVED_OBJECT_TYPE, serializeCounterKey } from './usage_c export type { UsageCollectionSetup } from './plugin'; export { config } from './config'; -export const plugin = (initializerContext: PluginInitializerContext) => - new UsageCollectionPlugin(initializerContext); +export const plugin = async (initializerContext: PluginInitializerContext) => { + const { UsageCollectionPlugin } = await import('./plugin'); + return new UsageCollectionPlugin(initializerContext); +}; diff --git a/src/plugins/vis_type_markdown/server/index.ts b/src/plugins/vis_type_markdown/server/index.ts index d2deba39e9987..3f3bae7d810d6 100644 --- a/src/plugins/vis_type_markdown/server/index.ts +++ b/src/plugins/vis_type_markdown/server/index.ts @@ -17,7 +17,7 @@ export const config: PluginConfigDescriptor = { ], }; -export const plugin = () => ({ +export const plugin = async () => ({ setup() {}, start() {}, }); diff --git a/src/plugins/vis_types/gauge/server/index.ts b/src/plugins/vis_types/gauge/server/index.ts index bffab6592194f..e6d35075c8fb0 100755 --- a/src/plugins/vis_types/gauge/server/index.ts +++ b/src/plugins/vis_types/gauge/server/index.ts @@ -8,7 +8,6 @@ import { PluginInitializerContext, PluginConfigDescriptor } from '@kbn/core/server'; import { configSchema, GaugeConfig } from '../config'; -import { VisTypeGaugeServerPlugin } from './plugin'; export const config: PluginConfigDescriptor = { exposeToBrowser: { @@ -17,5 +16,7 @@ export const config: PluginConfigDescriptor = { schema: configSchema, }; -export const plugin = (initializerContext: PluginInitializerContext) => - new VisTypeGaugeServerPlugin(initializerContext); +export const plugin = async (initializerContext: PluginInitializerContext) => { + const { VisTypeGaugeServerPlugin } = await import('./plugin'); + return new VisTypeGaugeServerPlugin(initializerContext); +}; diff --git a/src/plugins/vis_types/heatmap/server/index.ts b/src/plugins/vis_types/heatmap/server/index.ts index 752bf1a381563..34c3783b62c9b 100644 --- a/src/plugins/vis_types/heatmap/server/index.ts +++ b/src/plugins/vis_types/heatmap/server/index.ts @@ -8,7 +8,6 @@ import { PluginConfigDescriptor, PluginInitializerContext } from '@kbn/core/server'; import { configSchema, HeatmapConfig } from '../config'; -import { VisTypeHeatmapServerPlugin } from './plugin'; export const config: PluginConfigDescriptor = { exposeToBrowser: { @@ -17,5 +16,7 @@ export const config: PluginConfigDescriptor = { schema: configSchema, }; -export const plugin = (initializerContext: PluginInitializerContext) => - new VisTypeHeatmapServerPlugin(initializerContext); +export const plugin = async (initializerContext: PluginInitializerContext) => { + const { VisTypeHeatmapServerPlugin } = await import('./plugin'); + return new VisTypeHeatmapServerPlugin(initializerContext); +}; diff --git a/src/plugins/vis_types/metric/server/index.ts b/src/plugins/vis_types/metric/server/index.ts index 49359ab970e05..bc8d0b0f0f685 100644 --- a/src/plugins/vis_types/metric/server/index.ts +++ b/src/plugins/vis_types/metric/server/index.ts @@ -22,7 +22,7 @@ interface PluginSetupDependencies { visualizations: VisualizationsServerSetup; } -export const plugin = (initializerContext: PluginInitializerContext) => ({ +export const plugin = async (initializerContext: PluginInitializerContext) => ({ setup(core: CoreSetup, plugins: PluginSetupDependencies) { const { readOnly } = initializerContext.config.get(); if (readOnly) { diff --git a/src/plugins/vis_types/pie/server/index.ts b/src/plugins/vis_types/pie/server/index.ts index e1b9c6187357d..6b139e916adc9 100644 --- a/src/plugins/vis_types/pie/server/index.ts +++ b/src/plugins/vis_types/pie/server/index.ts @@ -8,7 +8,6 @@ import { PluginConfigDescriptor, PluginInitializerContext } from '@kbn/core/server'; import { configSchema, PieConfig } from '../config'; -import { VisTypePieServerPlugin } from './plugin'; export const config: PluginConfigDescriptor = { exposeToBrowser: { @@ -17,5 +16,7 @@ export const config: PluginConfigDescriptor = { schema: configSchema, }; -export const plugin = (initializerContext: PluginInitializerContext) => - new VisTypePieServerPlugin(initializerContext); +export const plugin = async (initializerContext: PluginInitializerContext) => { + const { VisTypePieServerPlugin } = await import('./plugin'); + return new VisTypePieServerPlugin(initializerContext); +}; diff --git a/src/plugins/vis_types/timelion/server/index.ts b/src/plugins/vis_types/timelion/server/index.ts index bdff2a33c3ab2..e9b312c8731b0 100644 --- a/src/plugins/vis_types/timelion/server/index.ts +++ b/src/plugins/vis_types/timelion/server/index.ts @@ -8,7 +8,6 @@ import { PluginConfigDescriptor, PluginInitializerContext } from '@kbn/core/server'; import { configSchema, TimelionConfig } from '../config'; -import { TimelionPlugin } from './plugin'; export const config: PluginConfigDescriptor = { exposeToBrowser: { @@ -18,5 +17,7 @@ export const config: PluginConfigDescriptor = { deprecations: ({ unused }) => [unused('graphiteUrls', { level: 'warning' })], }; -export const plugin = (initializerContext: PluginInitializerContext) => - new TimelionPlugin(initializerContext); +export const plugin = async (initializerContext: PluginInitializerContext) => { + const { TimelionPlugin } = await import('./plugin'); + return new TimelionPlugin(initializerContext); +}; diff --git a/src/plugins/vis_types/timeseries/server/index.ts b/src/plugins/vis_types/timeseries/server/index.ts index 0faecf4c03adc..9ecb8a92d27d8 100644 --- a/src/plugins/vis_types/timeseries/server/index.ts +++ b/src/plugins/vis_types/timeseries/server/index.ts @@ -8,7 +8,6 @@ import { PluginInitializerContext, PluginConfigDescriptor } from '@kbn/core/server'; import { VisTypeTimeseriesConfig, config as configSchema } from '../config'; -import { VisTypeTimeseriesPlugin } from './plugin'; export type { VisTypeTimeseriesSetup } from './plugin'; @@ -21,7 +20,8 @@ export const config: PluginConfigDescriptor = { schema: configSchema, }; -export function plugin(initializerContext: PluginInitializerContext) { +export async function plugin(initializerContext: PluginInitializerContext) { + const { VisTypeTimeseriesPlugin } = await import('./plugin'); return new VisTypeTimeseriesPlugin(initializerContext); } diff --git a/src/plugins/vis_types/vega/server/index.ts b/src/plugins/vis_types/vega/server/index.ts index 42e03c0ceefc5..b761d69922372 100644 --- a/src/plugins/vis_types/vega/server/index.ts +++ b/src/plugins/vis_types/vega/server/index.ts @@ -9,7 +9,6 @@ import { PluginConfigDescriptor, PluginInitializerContext } from '@kbn/core/server'; import { configSchema, ConfigSchema } from '../config'; -import { VisTypeVegaPlugin } from './plugin'; export const config: PluginConfigDescriptor = { exposeToBrowser: { @@ -18,7 +17,8 @@ export const config: PluginConfigDescriptor = { schema: configSchema, }; -export function plugin(initializerContext: PluginInitializerContext) { +export async function plugin(initializerContext: PluginInitializerContext) { + const { VisTypeVegaPlugin } = await import('./plugin'); return new VisTypeVegaPlugin(initializerContext); } diff --git a/src/plugins/vis_types/vislib/server/index.ts b/src/plugins/vis_types/vislib/server/index.ts index 8c46f2810542d..03b3d03d7fc25 100644 --- a/src/plugins/vis_types/vislib/server/index.ts +++ b/src/plugins/vis_types/vislib/server/index.ts @@ -8,7 +8,6 @@ import { PluginConfigDescriptor } from '@kbn/core/server'; import { configSchema, VislibConfig } from '../config'; -import { VisTypeVislibServerPlugin } from './plugin'; export const config: PluginConfigDescriptor = { exposeToBrowser: { @@ -17,4 +16,7 @@ export const config: PluginConfigDescriptor = { schema: configSchema, }; -export const plugin = () => new VisTypeVislibServerPlugin(); +export const plugin = async () => { + const { VisTypeVislibServerPlugin } = await import('./plugin'); + return new VisTypeVislibServerPlugin(); +}; diff --git a/src/plugins/vis_types/xy/server/index.ts b/src/plugins/vis_types/xy/server/index.ts index d6b73627dd73a..f0484adf9a5ec 100644 --- a/src/plugins/vis_types/xy/server/index.ts +++ b/src/plugins/vis_types/xy/server/index.ts @@ -8,7 +8,6 @@ import { PluginConfigDescriptor, PluginInitializerContext } from '@kbn/core/server'; import { configSchema, XyConfig } from '../config'; -import { VisTypeXYServerPlugin } from './plugin'; export const config: PluginConfigDescriptor = { exposeToBrowser: { @@ -17,5 +16,7 @@ export const config: PluginConfigDescriptor = { schema: configSchema, }; -export const plugin = (initializerContext: PluginInitializerContext) => - new VisTypeXYServerPlugin(initializerContext); +export const plugin = async (initializerContext: PluginInitializerContext) => { + const { VisTypeXYServerPlugin } = await import('./plugin'); + return new VisTypeXYServerPlugin(initializerContext); +}; diff --git a/src/plugins/visualizations/server/index.ts b/src/plugins/visualizations/server/index.ts index f40fb9885388f..adb65507d409c 100644 --- a/src/plugins/visualizations/server/index.ts +++ b/src/plugins/visualizations/server/index.ts @@ -7,12 +7,12 @@ */ import { PluginInitializerContext } from '@kbn/core/server'; -import { VisualizationsPlugin } from './plugin'; // This exports static code and TypeScript types, // as well as, Kibana Platform `plugin()` initializer. -export function plugin(initializerContext: PluginInitializerContext) { +export async function plugin(initializerContext: PluginInitializerContext) { + const { VisualizationsPlugin } = await import('./plugin'); return new VisualizationsPlugin(initializerContext); } diff --git a/test/analytics/plugins/analytics_ftr_helpers/server/index.ts b/test/analytics/plugins/analytics_ftr_helpers/server/index.ts index 637348226e25c..190ec73cdd08e 100644 --- a/test/analytics/plugins/analytics_ftr_helpers/server/index.ts +++ b/test/analytics/plugins/analytics_ftr_helpers/server/index.ts @@ -8,4 +8,4 @@ import { AnalyticsFTRHelpers } from './plugin'; -export const plugin = () => new AnalyticsFTRHelpers(); +export const plugin = async () => new AnalyticsFTRHelpers(); diff --git a/test/analytics/plugins/analytics_plugin_a/server/index.ts b/test/analytics/plugins/analytics_plugin_a/server/index.ts index 65d2593c427f5..3decfbd0b4201 100644 --- a/test/analytics/plugins/analytics_plugin_a/server/index.ts +++ b/test/analytics/plugins/analytics_plugin_a/server/index.ts @@ -8,4 +8,4 @@ import { AnalyticsPluginAPlugin } from './plugin'; -export const plugin = () => new AnalyticsPluginAPlugin(); +export const plugin = async () => new AnalyticsPluginAPlugin(); 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 2920d0a9d09bf..aa11e35249509 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 @@ -13,41 +13,36 @@ import { FtrProviderContext } from '../../../services'; export default function ({ getService }: FtrProviderContext) { const ebtServerHelper = getService('kibana_ebt_server'); - // Failing: See https://github.com/elastic/kibana/issues/171164 - describe.skip('core-overall_status_changed', () => { - let initialEvent: Event>; - let secondEvent: Event>; + describe('core-overall_status_changed', () => { + let currentEvent: Event>; before(async () => { - [initialEvent, secondEvent] = await ebtServerHelper.getEvents(2, { + [currentEvent] = await ebtServerHelper.getEvents(1, { eventTypes: ['core-overall_status_changed'], }); }); - it('should emit the initial "degraded" event with the context set to `initializing`', () => { + it('should emit an initial event with the context set to `initializing`', async () => { + const initialEvent = currentEvent; expect(initialEvent.event_type).to.eql('core-overall_status_changed'); - expect(initialEvent.context).to.have.property('overall_status_level', 'initializing'); - expect(initialEvent.context).to.have.property( - 'overall_status_summary', - 'Kibana is starting up' - ); - expect(initialEvent.properties).to.have.property('overall_status_level', 'degraded'); - expect(initialEvent.properties).to.have.property('overall_status_summary'); - expect(initialEvent.properties.overall_status_summary).to.be.a('string'); + expect(initialEvent.context.overall_status_level).to.eql('initializing'); + expect(initialEvent.context.overall_status_summary).to.eql('Kibana is starting up'); }); - it('should emit the 2nd event as `available` with the context set to the previous values', () => { - expect(secondEvent.event_type).to.eql('core-overall_status_changed'); - expect(secondEvent.context).to.have.property( - 'overall_status_level', - initialEvent.properties.overall_status_level - ); - expect(secondEvent.context).to.have.property( - 'overall_status_summary', - initialEvent.properties.overall_status_summary - ); - expect(secondEvent.properties.overall_status_level).to.be.a('string'); // Ideally we would test it as `available`, but we can't do that as it may result flaky for many side effects in the CI. - expect(secondEvent.properties.overall_status_summary).to.be.a('string'); + it('should emit an event with status `available` eventually', async () => { + const isAvailable = (ev: Event>) => + ev.properties.overall_status_level === 'available'; + + for (let i = 2; i <= 10 && !isAvailable(currentEvent); ++i) { + currentEvent = ( + await ebtServerHelper.getEvents(i, { + eventTypes: ['core-overall_status_changed'], + }) + ).pop()!; + } + + // at this point, Kibana is NOT available after 10 emissions! + expect(isAvailable(currentEvent)).to.eql(true); }); }); } diff --git a/test/common/plugins/newsfeed/server/index.ts b/test/common/plugins/newsfeed/server/index.ts index 21e28f5435cc2..192de4a3c47e3 100644 --- a/test/common/plugins/newsfeed/server/index.ts +++ b/test/common/plugins/newsfeed/server/index.ts @@ -9,6 +9,6 @@ import type { PluginInitializerContext } from '@kbn/core/server'; import { NewsFeedSimulatorPlugin } from './plugin'; -export function plugin(initializerContext: PluginInitializerContext) { +export async function plugin(initializerContext: PluginInitializerContext) { return new NewsFeedSimulatorPlugin(initializerContext); } diff --git a/test/common/plugins/otel_metrics/server/index.ts b/test/common/plugins/otel_metrics/server/index.ts index eb5f587592cae..2e542342b04c0 100644 --- a/test/common/plugins/otel_metrics/server/index.ts +++ b/test/common/plugins/otel_metrics/server/index.ts @@ -8,4 +8,4 @@ import { OpenTelemetryUsageTest } from './plugin'; -export const plugin = () => new OpenTelemetryUsageTest(); +export const plugin = async () => new OpenTelemetryUsageTest(); diff --git a/test/functional/apps/console/_xjson.ts b/test/functional/apps/console/_xjson.ts index 1535337a2a848..6a4f352a3ad01 100644 --- a/test/functional/apps/console/_xjson.ts +++ b/test/functional/apps/console/_xjson.ts @@ -15,7 +15,9 @@ export default ({ getService, getPageObjects }: FtrProviderContext) => { const log = getService('log'); const PageObjects = getPageObjects(['common', 'console', 'header']); - describe('XJSON', function testXjson() { + // FLAKY: https://github.com/elastic/kibana/issues/171259 + // FLAKY: https://github.com/elastic/kibana/issues/158484 + describe.skip('XJSON', function testXjson() { this.tags('includeFirefox'); before(async () => { await PageObjects.common.navigateToApp('console'); diff --git a/test/functional/apps/discover/ccs_compatibility/_search_errors.ts b/test/functional/apps/discover/ccs_compatibility/_search_errors.ts new file mode 100644 index 0000000000000..da2d2b5567341 --- /dev/null +++ b/test/functional/apps/discover/ccs_compatibility/_search_errors.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 config = getService('config'); + const filterBar = getService('filterBar'); + const kibanaServer = getService('kibanaServer'); + const retry = getService('retry'); + const testSubjects = getService('testSubjects'); + const PageObjects = getPageObjects(['common', 'discover', 'header', 'timePicker']); + + const isCcsTest = config.get('esTestCluster.ccs'); + const archiveDirectory = isCcsTest + ? 'test/functional/fixtures/kbn_archiver/ccs/discover.json' + : 'test/functional/fixtures/kbn_archiver/discover.json'; + const esNode = isCcsTest + ? getService('remoteEsArchiver' as 'esArchiver') + : getService('esArchiver'); + + const defaultIndex = isCcsTest ? 'ftr-remote:logstash-*' : 'logstash-*'; + + describe('discover search errors', () => { + before(async () => { + await kibanaServer.importExport.load(archiveDirectory); + await esNode.loadIfNeeded('test/functional/fixtures/es_archiver/logstash_functional'); + }); + + after(async () => { + await kibanaServer.importExport.unload(archiveDirectory); + await esNode.unload('test/functional/fixtures/es_archiver/logstash_functional'); + }); + + it('exception on single shard shows warning and results', async () => { + await PageObjects.common.navigateToApp('discover'); + await PageObjects.discover.selectIndexPattern(defaultIndex); + await PageObjects.timePicker.setDefaultAbsoluteRange(); + await retry.try(async () => { + const hitCount = await PageObjects.discover.getHitCount(); + expect(hitCount).to.be('14,004'); + }); + await filterBar.addDslFilter(` + { + "query": { + "error_query": { + "indices": [ + { + "name": "${defaultIndex.slice(0, defaultIndex.length - 1)}2015.09.20", + "error_type": "exception", + "message": "'Watch out!'" + } + ] + } + } + }`); + + // Ensure documents are still returned for the successful shards + await retry.try(async function tryingForTime() { + const hitCount = await PageObjects.discover.getHitCount(); + expect(hitCount).to.be('9,247'); + }); + + // Ensure a warning is shown + await testSubjects.exists('searchResponseWarningsCallout'); + }); + + it('exception on all shards shows error', async () => { + await PageObjects.common.navigateToApp('discover'); + await PageObjects.discover.selectIndexPattern(defaultIndex); + await PageObjects.timePicker.setDefaultAbsoluteRange(); + await retry.try(async () => { + const hitCount = await PageObjects.discover.getHitCount(); + expect(hitCount).to.be('14,004'); + }); + await filterBar.addDslFilter(` + { + "query": { + "error_query": { + "indices": [ + { + "name": "${defaultIndex}", + "error_type": "exception", + "message": "'Watch out!'" + } + ] + } + } + }`); + + // Ensure an error is shown + await testSubjects.exists('searchResponseWarningsEmptyPrompt'); + }); + }); +} diff --git a/test/functional/apps/discover/ccs_compatibility/index.ts b/test/functional/apps/discover/ccs_compatibility/index.ts index 1204ce9daadb2..4f932c3993831 100644 --- a/test/functional/apps/discover/ccs_compatibility/index.ts +++ b/test/functional/apps/discover/ccs_compatibility/index.ts @@ -22,5 +22,6 @@ export default function ({ getService, loadTestFile }: FtrProviderContext) { loadTestFile(require.resolve('./_data_view_editor')); loadTestFile(require.resolve('./_saved_queries')); + loadTestFile(require.resolve('./_search_errors')); }); } diff --git a/test/functional/apps/discover/group3/_default_columns.ts b/test/functional/apps/discover/group3/_default_columns.ts new file mode 100644 index 0000000000000..64028c54a1b19 --- /dev/null +++ b/test/functional/apps/discover/group3/_default_columns.ts @@ -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 and the Server Side Public License, v 1; you may 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 dataGrid = getService('dataGrid'); + const PageObjects = getPageObjects([ + 'common', + 'discover', + 'timePicker', + 'unifiedFieldList', + 'unifiedSearch', + 'header', + ]); + const esArchiver = getService('esArchiver'); + const kibanaServer = getService('kibanaServer'); + const security = getService('security'); + const defaultSettings = { + defaultIndex: 'logstash-*', + defaultColumns: ['message', 'extension', 'DestCountry'], + hideAnnouncements: true, + }; + + describe('discover default columns', function () { + before(async () => { + await security.testUser.setRoles(['kibana_admin', 'test_logstash_reader']); + await esArchiver.loadIfNeeded('test/functional/fixtures/es_archiver/logstash_functional'); + await esArchiver.load('test/functional/fixtures/es_archiver/kibana_sample_data_logs_tsdb'); + await esArchiver.loadIfNeeded( + 'test/functional/fixtures/es_archiver/kibana_sample_data_flights' + ); + await kibanaServer.importExport.load('test/functional/fixtures/kbn_archiver/discover'); + await kibanaServer.importExport.load( + 'test/functional/fixtures/kbn_archiver/kibana_sample_data_logs_tsdb' + ); + await kibanaServer.importExport.load( + 'test/functional/fixtures/kbn_archiver/kibana_sample_data_flights_index_pattern' + ); + }); + + after(async () => { + await kibanaServer.importExport.unload('test/functional/fixtures/kbn_archiver/discover'); + await esArchiver.unload('test/functional/fixtures/es_archiver/logstash_functional'); + await esArchiver.unload('test/functional/fixtures/es_archiver/kibana_sample_data_logs_tsdb'); + await esArchiver.unload('test/functional/fixtures/es_archiver/kibana_sample_data_flights'); + await kibanaServer.savedObjects.cleanStandardList(); + }); + + beforeEach(async function () { + await PageObjects.timePicker.setDefaultAbsoluteRangeViaUiSettings(); + await kibanaServer.uiSettings.update(defaultSettings); + await PageObjects.common.navigateToApp('discover'); + await PageObjects.discover.waitUntilSearchingHasFinished(); + }); + + it('should render default columns', async function () { + expect(await dataGrid.getHeaderFields()).to.eql([ + '@timestamp', + 'message', + 'extension', + 'DestCountry', + ]); + }); + + it('should render only available default columns after switching data views', async function () { + expect(await dataGrid.getHeaderFields()).to.eql([ + '@timestamp', + 'message', + 'extension', + 'DestCountry', + ]); + + await PageObjects.unifiedSearch.switchDataView( + 'discover-dataView-switch-link', + 'Kibana Sample Data Logs (TSDB)', + false + ); + await PageObjects.discover.waitUntilSearchingHasFinished(); + await PageObjects.discover.expandTimeRangeAsSuggestedInNoResultsMessage(); + await PageObjects.discover.waitUntilSearchingHasFinished(); + expect(await dataGrid.getHeaderFields()).to.eql(['timestamp', 'message', 'extension']); + + await PageObjects.unifiedSearch.switchDataView( + 'discover-dataView-switch-link', + 'kibana_sample_data_flights', + false + ); + await PageObjects.discover.waitUntilSearchingHasFinished(); + await PageObjects.discover.expandTimeRangeAsSuggestedInNoResultsMessage(); + await PageObjects.discover.waitUntilSearchingHasFinished(); + expect(await dataGrid.getHeaderFields()).to.eql(['timestamp', 'DestCountry']); + + await PageObjects.unifiedSearch.switchDataView( + 'discover-dataView-switch-link', + 'logstash-*', + false + ); + await PageObjects.discover.waitUntilSearchingHasFinished(); + await PageObjects.discover.expandTimeRangeAsSuggestedInNoResultsMessage(); + await PageObjects.discover.waitUntilSearchingHasFinished(); + expect(await dataGrid.getHeaderFields()).to.eql(['@timestamp', 'extension']); + }); + + it('should combine selected columns and default columns after switching data views', async function () { + await PageObjects.unifiedFieldList.clickFieldListItemAdd('bytes'); + await PageObjects.unifiedFieldList.clickFieldListItemRemove('DestCountry'); + await PageObjects.unifiedFieldList.clickFieldListItemRemove('message'); + await PageObjects.discover.waitUntilSearchingHasFinished(); + + expect(await dataGrid.getHeaderFields()).to.eql(['@timestamp', 'extension', 'bytes']); + + await PageObjects.unifiedSearch.switchDataView( + 'discover-dataView-switch-link', + 'Kibana Sample Data Logs (TSDB)', + false + ); + await PageObjects.discover.waitUntilSearchingHasFinished(); + await PageObjects.discover.expandTimeRangeAsSuggestedInNoResultsMessage(); + await PageObjects.discover.waitUntilSearchingHasFinished(); + expect(await dataGrid.getHeaderFields()).to.eql([ + 'timestamp', + 'extension', + 'bytes', + 'message', + ]); + + await PageObjects.unifiedSearch.switchDataView( + 'discover-dataView-switch-link', + 'logstash-*', + false + ); + await PageObjects.discover.waitUntilSearchingHasFinished(); + await PageObjects.discover.expandTimeRangeAsSuggestedInNoResultsMessage(); + await PageObjects.discover.waitUntilSearchingHasFinished(); + expect(await dataGrid.getHeaderFields()).to.eql(['@timestamp', 'extension', 'bytes']); + }); + + it('should not change columns if discover:modifyColumnsOnSwitch is off', async function () { + await kibanaServer.uiSettings.update({ + 'discover:modifyColumnsOnSwitch': false, + }); + await PageObjects.common.navigateToApp('discover'); + await PageObjects.discover.waitUntilSearchingHasFinished(); + + expect(await dataGrid.getHeaderFields()).to.eql([ + '@timestamp', + 'message', + 'extension', + 'DestCountry', + ]); + + await PageObjects.unifiedSearch.switchDataView( + 'discover-dataView-switch-link', + 'kibana_sample_data_flights', + false + ); + await PageObjects.discover.waitUntilSearchingHasFinished(); + await PageObjects.discover.expandTimeRangeAsSuggestedInNoResultsMessage(); + await PageObjects.discover.waitUntilSearchingHasFinished(); + expect(await dataGrid.getHeaderFields()).to.eql([ + 'timestamp', + 'message', + 'extension', + 'DestCountry', + ]); + }); + }); +} diff --git a/test/functional/apps/discover/group3/index.ts b/test/functional/apps/discover/group3/index.ts index 4ac4572014a52..848bdc84def4d 100644 --- a/test/functional/apps/discover/group3/index.ts +++ b/test/functional/apps/discover/group3/index.ts @@ -20,6 +20,7 @@ export default function ({ getService, loadTestFile }: FtrProviderContext) { await esArchiver.unload('test/functional/fixtures/es_archiver/logstash_functional'); }); + loadTestFile(require.resolve('./_default_columns')); loadTestFile(require.resolve('./_drag_drop')); loadTestFile(require.resolve('./_sidebar')); loadTestFile(require.resolve('./_request_counts')); diff --git a/test/functional/apps/management/data_views/_data_view_create_delete.ts b/test/functional/apps/management/data_views/_data_view_create_delete.ts index edf2f000fcb27..e3bc2240887ad 100644 --- a/test/functional/apps/management/data_views/_data_view_create_delete.ts +++ b/test/functional/apps/management/data_views/_data_view_create_delete.ts @@ -17,6 +17,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { const retry = getService('retry'); const testSubjects = getService('testSubjects'); const find = getService('find'); + const es = getService('es'); const PageObjects = getPageObjects(['settings', 'common', 'header']); describe('creating and deleting default data view', function describeIndexTests() { @@ -250,5 +251,41 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { }); }); }); + + describe('hidden index support', () => { + it('can create data view against hidden index', async () => { + const pattern = 'logstash-2015.09.2*'; + + await es.transport.request({ + path: '/logstash-2015.09.2*/_settings', + method: 'PUT', + body: { + index: { + hidden: true, + }, + }, + }); + + await PageObjects.settings.createIndexPattern( + pattern, + '@timestamp', + undefined, + undefined, + undefined, + true + ); + const patternName = await PageObjects.settings.getIndexPageHeading(); + expect(patternName).to.be(pattern); + + // verify that allow hidden persists through reload + await browser.refresh(); + + await testSubjects.click('editIndexPatternButton'); + await testSubjects.click('toggleAdvancedSetting'); + const allowHiddenField = await testSubjects.find('allowHiddenField'); + const button = await allowHiddenField.findByTagName('button'); + expect(await button.getAttribute('aria-checked')).to.be('true'); + }); + }); }); } diff --git a/test/functional/page_objects/settings_page.ts b/test/functional/page_objects/settings_page.ts index 0a2fd76076914..5172d7d7d0ff4 100644 --- a/test/functional/page_objects/settings_page.ts +++ b/test/functional/page_objects/settings_page.ts @@ -483,13 +483,20 @@ export class SettingsPageObject extends FtrService { await customDataViewIdInput.type(value); } + async allowHiddenClick() { + await this.testSubjects.click('toggleAdvancedSetting'); + const allowHiddenField = await this.testSubjects.find('allowHiddenField'); + (await allowHiddenField.findByTagName('button')).click(); + } + async createIndexPattern( indexPatternName: string, // null to bypass default value timefield: string | null = '@timestamp', isStandardIndexPattern = true, customDataViewId?: string, - dataViewName?: string + dataViewName?: string, + allowHidden?: boolean ) { await this.retry.try(async () => { await this.header.waitUntilLoadingHasFinished(); @@ -502,6 +509,11 @@ export class SettingsPageObject extends FtrService { } else { await this.clickAddNewIndexPatternButton(); } + + if (allowHidden) { + await this.allowHiddenClick(); + } + await this.header.waitUntilLoadingHasFinished(); if (!isStandardIndexPattern) { await this.selectRollupIndexPatternType(); diff --git a/test/functional/services/filter_bar.ts b/test/functional/services/filter_bar.ts index 22fa4ff0b5e59..eb9aae45621e1 100644 --- a/test/functional/services/filter_bar.ts +++ b/test/functional/services/filter_bar.ts @@ -65,6 +65,7 @@ type Filter = FilterLeaf | FilterNode; export class FilterBarService extends FtrService { private readonly comboBox = this.ctx.getService('comboBox'); + private readonly monacoEditor = this.ctx.getService('monacoEditor'); private readonly testSubjects = this.ctx.getService('testSubjects'); private readonly common = this.ctx.getPageObject('common'); private readonly header = this.ctx.getPageObject('header'); @@ -315,6 +316,19 @@ export class FilterBarService extends FtrService { await this.addFilterAndSelectDataView(null, filter); } + public async addDslFilter(value: string) { + await this.testSubjects.click('addFilter'); + await this.testSubjects.click('editQueryDSL'); + await this.monacoEditor.waitCodeEditorReady('addFilterPopover'); + await this.monacoEditor.setCodeEditorValue(value); + await this.testSubjects.scrollIntoView('saveFilter'); + await this.testSubjects.clickWhenNotDisabled('saveFilter'); + await this.retry.try(async () => { + await this.testSubjects.waitForDeleted('saveFilter'); + }); + await this.header.waitUntilLoadingHasFinished(); + } + /** * Activates filter editing * @param key field name diff --git a/test/health_gateway/plugins/status/server/index.ts b/test/health_gateway/plugins/status/server/index.ts index a71049da757d0..d37e063cbe12f 100644 --- a/test/health_gateway/plugins/status/server/index.ts +++ b/test/health_gateway/plugins/status/server/index.ts @@ -8,6 +8,6 @@ import { HealthGatewayStatusPlugin } from './plugin'; -export function plugin() { +export async function plugin() { return new HealthGatewayStatusPlugin(); } diff --git a/test/interactive_setup_api_integration/plugins/test_endpoints/server/index.ts b/test/interactive_setup_api_integration/plugins/test_endpoints/server/index.ts index 8af208ce69da9..838998c86d6a8 100644 --- a/test/interactive_setup_api_integration/plugins/test_endpoints/server/index.ts +++ b/test/interactive_setup_api_integration/plugins/test_endpoints/server/index.ts @@ -11,7 +11,9 @@ import path from 'path'; import type { PluginInitializer, PrebootPlugin } from '@kbn/core/server'; -export const plugin: PluginInitializer = (initializerContext): PrebootPlugin => ({ +export const plugin: PluginInitializer = async ( + initializerContext +): Promise => ({ setup: (core) => { core.http.registerRoutes('', (router) => { router.get( diff --git a/test/interpreter_functional/plugins/kbn_tp_run_pipeline/server/index.ts b/test/interpreter_functional/plugins/kbn_tp_run_pipeline/server/index.ts index 0230677a9d7e1..004d5bda160f3 100644 --- a/test/interpreter_functional/plugins/kbn_tp_run_pipeline/server/index.ts +++ b/test/interpreter_functional/plugins/kbn_tp_run_pipeline/server/index.ts @@ -9,4 +9,5 @@ import { PluginInitializer } from '@kbn/core/server'; import { TestPlugin, TestPluginSetup, TestPluginStart } from './plugin'; -export const plugin: PluginInitializer = () => new TestPlugin(); +export const plugin: PluginInitializer = async () => + new TestPlugin(); diff --git a/test/node_roles_functional/plugins/core_plugin_initializer_context/server/index.ts b/test/node_roles_functional/plugins/core_plugin_initializer_context/server/index.ts index c074b4997a7f8..fa2e178f6a688 100644 --- a/test/node_roles_functional/plugins/core_plugin_initializer_context/server/index.ts +++ b/test/node_roles_functional/plugins/core_plugin_initializer_context/server/index.ts @@ -9,5 +9,5 @@ import type { PluginInitializerContext } from '@kbn/core/server'; import { CorePluginInitializerContextPlugin } from './plugin'; -export const plugin = (initializerContext: PluginInitializerContext) => +export const plugin = async (initializerContext: PluginInitializerContext) => new CorePluginInitializerContextPlugin(initializerContext); diff --git a/test/plugin_functional/plugins/core_dynamic_resolving_a/server/index.ts b/test/plugin_functional/plugins/core_dynamic_resolving_a/server/index.ts index dc204bdfdea9e..2b673ae30180c 100644 --- a/test/plugin_functional/plugins/core_dynamic_resolving_a/server/index.ts +++ b/test/plugin_functional/plugins/core_dynamic_resolving_a/server/index.ts @@ -8,4 +8,4 @@ import { CoreDynamicResolvingAPlugin } from './plugin'; -export const plugin = () => new CoreDynamicResolvingAPlugin(); +export const plugin = async () => new CoreDynamicResolvingAPlugin(); diff --git a/test/plugin_functional/plugins/core_dynamic_resolving_b/server/index.ts b/test/plugin_functional/plugins/core_dynamic_resolving_b/server/index.ts index ed305f96d7bc9..57797605cd46e 100644 --- a/test/plugin_functional/plugins/core_dynamic_resolving_b/server/index.ts +++ b/test/plugin_functional/plugins/core_dynamic_resolving_b/server/index.ts @@ -8,4 +8,4 @@ import { CoreDynamicResolvingBPlugin } from './plugin'; -export const plugin = () => new CoreDynamicResolvingBPlugin(); +export const plugin = async () => new CoreDynamicResolvingBPlugin(); diff --git a/test/plugin_functional/plugins/core_http/server/index.ts b/test/plugin_functional/plugins/core_http/server/index.ts index 66c2bb9e676f3..7f95feacaf444 100644 --- a/test/plugin_functional/plugins/core_http/server/index.ts +++ b/test/plugin_functional/plugins/core_http/server/index.ts @@ -8,4 +8,4 @@ import { CoreHttpPlugin } from './plugin'; -export const plugin = () => new CoreHttpPlugin(); +export const plugin = async () => new CoreHttpPlugin(); diff --git a/test/plugin_functional/plugins/core_plugin_a/server/index.ts b/test/plugin_functional/plugins/core_plugin_a/server/index.ts index 7fad3cf7a9e3b..a64b4f81d205a 100644 --- a/test/plugin_functional/plugins/core_plugin_a/server/index.ts +++ b/test/plugin_functional/plugins/core_plugin_a/server/index.ts @@ -9,4 +9,4 @@ import { CorePluginAPlugin } from './plugin'; export type { PluginAApiRequestContext } from './plugin'; -export const plugin = () => new CorePluginAPlugin(); +export const plugin = async () => new CorePluginAPlugin(); diff --git a/test/plugin_functional/plugins/core_plugin_b/server/index.ts b/test/plugin_functional/plugins/core_plugin_b/server/index.ts index da2c29c64b0be..e12621c34b3d7 100644 --- a/test/plugin_functional/plugins/core_plugin_b/server/index.ts +++ b/test/plugin_functional/plugins/core_plugin_b/server/index.ts @@ -8,4 +8,4 @@ import { CorePluginBPlugin } from './plugin'; -export const plugin = () => new CorePluginBPlugin(); +export const plugin = async () => new CorePluginBPlugin(); diff --git a/test/plugin_functional/plugins/core_plugin_deprecations/server/index.ts b/test/plugin_functional/plugins/core_plugin_deprecations/server/index.ts index 1968c011a327a..e7f934ac66a1c 100644 --- a/test/plugin_functional/plugins/core_plugin_deprecations/server/index.ts +++ b/test/plugin_functional/plugins/core_plugin_deprecations/server/index.ts @@ -9,4 +9,4 @@ import { CorePluginDeprecationsPlugin } from './plugin'; export { config } from './config'; -export const plugin = () => new CorePluginDeprecationsPlugin(); +export const plugin = async () => new CorePluginDeprecationsPlugin(); diff --git a/test/plugin_functional/plugins/core_plugin_execution_context/server/index.ts b/test/plugin_functional/plugins/core_plugin_execution_context/server/index.ts index 019e302096752..029710faab2c7 100644 --- a/test/plugin_functional/plugins/core_plugin_execution_context/server/index.ts +++ b/test/plugin_functional/plugins/core_plugin_execution_context/server/index.ts @@ -8,4 +8,4 @@ import { CorePluginExecutionContext } from './plugin'; -export const plugin = () => new CorePluginExecutionContext(); +export const plugin = async () => new CorePluginExecutionContext(); diff --git a/test/plugin_functional/plugins/core_plugin_route_timeouts/server/index.ts b/test/plugin_functional/plugins/core_plugin_route_timeouts/server/index.ts index 47dcc66303a4e..5fbb9113cb59c 100644 --- a/test/plugin_functional/plugins/core_plugin_route_timeouts/server/index.ts +++ b/test/plugin_functional/plugins/core_plugin_route_timeouts/server/index.ts @@ -8,4 +8,4 @@ import { CorePluginRouteTimeoutsPlugin } from './plugin'; -export const plugin = () => new CorePluginRouteTimeoutsPlugin(); +export const plugin = async () => new CorePluginRouteTimeoutsPlugin(); diff --git a/test/plugin_functional/plugins/data_search/server/index.ts b/test/plugin_functional/plugins/data_search/server/index.ts index f7fb397aaedaa..8d2412d0192d7 100644 --- a/test/plugin_functional/plugins/data_search/server/index.ts +++ b/test/plugin_functional/plugins/data_search/server/index.ts @@ -9,5 +9,5 @@ import { PluginInitializer } from '@kbn/core/server'; import { DataSearchTestPlugin, TestPluginSetup, TestPluginStart } from './plugin'; -export const plugin: PluginInitializer = () => +export const plugin: PluginInitializer = async () => new DataSearchTestPlugin(); diff --git a/test/plugin_functional/plugins/elasticsearch_client_plugin/server/index.ts b/test/plugin_functional/plugins/elasticsearch_client_plugin/server/index.ts index f484a8e30985a..6e5b765d3ab18 100644 --- a/test/plugin_functional/plugins/elasticsearch_client_plugin/server/index.ts +++ b/test/plugin_functional/plugins/elasticsearch_client_plugin/server/index.ts @@ -8,4 +8,4 @@ import { ElasticsearchClientPlugin } from './plugin'; -export const plugin = () => new ElasticsearchClientPlugin(); +export const plugin = async () => new ElasticsearchClientPlugin(); diff --git a/test/plugin_functional/plugins/index_patterns/server/index.ts b/test/plugin_functional/plugins/index_patterns/server/index.ts index e40b2e7534bfb..5f723ef27a884 100644 --- a/test/plugin_functional/plugins/index_patterns/server/index.ts +++ b/test/plugin_functional/plugins/index_patterns/server/index.ts @@ -16,4 +16,4 @@ import { export const plugin: PluginInitializer< IndexPatternsTestPluginSetup, IndexPatternsTestPluginStart -> = () => new IndexPatternsTestPlugin(); +> = async () => new IndexPatternsTestPlugin(); diff --git a/test/plugin_functional/plugins/rendering_plugin/server/index.ts b/test/plugin_functional/plugins/rendering_plugin/server/index.ts index 9c684205df36a..156c0ecf3484c 100644 --- a/test/plugin_functional/plugins/rendering_plugin/server/index.ts +++ b/test/plugin_functional/plugins/rendering_plugin/server/index.ts @@ -8,4 +8,4 @@ import { RenderingPlugin } from './plugin'; -export const plugin = () => new RenderingPlugin(); +export const plugin = async () => new RenderingPlugin(); diff --git a/test/plugin_functional/plugins/saved_object_export_transforms/server/index.ts b/test/plugin_functional/plugins/saved_object_export_transforms/server/index.ts index ff622c41ad367..758620d7a75ba 100644 --- a/test/plugin_functional/plugins/saved_object_export_transforms/server/index.ts +++ b/test/plugin_functional/plugins/saved_object_export_transforms/server/index.ts @@ -8,4 +8,4 @@ import { SavedObjectExportTransformsPlugin } from './plugin'; -export const plugin = () => new SavedObjectExportTransformsPlugin(); +export const plugin = async () => new SavedObjectExportTransformsPlugin(); diff --git a/test/plugin_functional/plugins/saved_object_import_warnings/server/index.ts b/test/plugin_functional/plugins/saved_object_import_warnings/server/index.ts index c6bbdda012b74..9f9d617a6a727 100644 --- a/test/plugin_functional/plugins/saved_object_import_warnings/server/index.ts +++ b/test/plugin_functional/plugins/saved_object_import_warnings/server/index.ts @@ -8,4 +8,4 @@ import { SavedObjectImportWarningsPlugin } from './plugin'; -export const plugin = () => new SavedObjectImportWarningsPlugin(); +export const plugin = async () => new SavedObjectImportWarningsPlugin(); diff --git a/test/plugin_functional/plugins/saved_objects_hidden_from_http_apis_type/server/index.ts b/test/plugin_functional/plugins/saved_objects_hidden_from_http_apis_type/server/index.ts index 6e0e8ae655479..af0e09a3ef067 100644 --- a/test/plugin_functional/plugins/saved_objects_hidden_from_http_apis_type/server/index.ts +++ b/test/plugin_functional/plugins/saved_objects_hidden_from_http_apis_type/server/index.ts @@ -8,4 +8,4 @@ import { SavedObjectsHiddenFromHttpApisTypePlugin } from './plugin'; -export const plugin = () => new SavedObjectsHiddenFromHttpApisTypePlugin(); +export const plugin = async () => new SavedObjectsHiddenFromHttpApisTypePlugin(); diff --git a/test/plugin_functional/plugins/saved_objects_hidden_type/server/index.ts b/test/plugin_functional/plugins/saved_objects_hidden_type/server/index.ts index 2093b6e8449a4..738bb64d61ec9 100644 --- a/test/plugin_functional/plugins/saved_objects_hidden_type/server/index.ts +++ b/test/plugin_functional/plugins/saved_objects_hidden_type/server/index.ts @@ -8,4 +8,4 @@ import { SavedObjectsHiddenTypePlugin } from './plugin'; -export const plugin = () => new SavedObjectsHiddenTypePlugin(); +export const plugin = async () => new SavedObjectsHiddenTypePlugin(); diff --git a/test/plugin_functional/plugins/ui_settings_plugin/server/index.ts b/test/plugin_functional/plugins/ui_settings_plugin/server/index.ts index 581277501a489..8df0dce5cebf4 100644 --- a/test/plugin_functional/plugins/ui_settings_plugin/server/index.ts +++ b/test/plugin_functional/plugins/ui_settings_plugin/server/index.ts @@ -8,4 +8,4 @@ import { UiSettingsPlugin } from './plugin'; -export const plugin = () => new UiSettingsPlugin(); +export const plugin = async () => new UiSettingsPlugin(); diff --git a/test/plugin_functional/plugins/usage_collection/server/index.ts b/test/plugin_functional/plugins/usage_collection/server/index.ts index 172f8491a1a40..aee68cb614f46 100644 --- a/test/plugin_functional/plugins/usage_collection/server/index.ts +++ b/test/plugin_functional/plugins/usage_collection/server/index.ts @@ -7,4 +7,4 @@ */ import { UsageCollectionTestPlugin } from './plugin'; -export const plugin = () => new UsageCollectionTestPlugin(); +export const plugin = async () => new UsageCollectionTestPlugin(); diff --git a/test/server_integration/http/platform/config.status.ts b/test/server_integration/http/platform/config.status.ts index 638d850a8f75c..53ff1e609f689 100644 --- a/test/server_integration/http/platform/config.status.ts +++ b/test/server_integration/http/platform/config.status.ts @@ -40,7 +40,8 @@ export default async function ({ readConfigFile }: FtrConfigProviderContext) { runOptions: { ...httpConfig.get('kbnTestServer.runOptions'), // Don't wait for Kibana to be completely ready so that we can test the status timeouts - wait: /Kibana is now unavailable/, + // but wait for http service to listen. + wait: /\[http\.server\.Kibana\] http server running at/, alwaysUseSource: true, }, }, diff --git a/test/server_integration/http/platform/status.ts b/test/server_integration/http/platform/status.ts index 50c136bfa1027..8ce193c670849 100644 --- a/test/server_integration/http/platform/status.ts +++ b/test/server_integration/http/platform/status.ts @@ -32,7 +32,7 @@ export default function ({ getService }: FtrProviderContext) { .expect(200); describe('status service', () => { - // This test must comes first because the timeout only applies to the initial emission + // This test must come first because the timeout only applies to the initial emission it("returns a timeout for status check that doesn't emit after 30s", async () => { let aStatus = await getStatus('statusPluginA'); expect(aStatus.level).to.eql('unavailable'); diff --git a/test/server_integration/plugins/status_plugin_a/server/index.ts b/test/server_integration/plugins/status_plugin_a/server/index.ts index cf221c00e32b0..9f001ed0133fe 100644 --- a/test/server_integration/plugins/status_plugin_a/server/index.ts +++ b/test/server_integration/plugins/status_plugin_a/server/index.ts @@ -8,4 +8,4 @@ import { StatusPluginAPlugin } from './plugin'; -export const plugin = () => new StatusPluginAPlugin(); +export const plugin = async () => new StatusPluginAPlugin(); diff --git a/test/server_integration/plugins/status_plugin_b/server/index.ts b/test/server_integration/plugins/status_plugin_b/server/index.ts index 2002d234827b9..db400f1a0e23a 100644 --- a/test/server_integration/plugins/status_plugin_b/server/index.ts +++ b/test/server_integration/plugins/status_plugin_b/server/index.ts @@ -8,4 +8,4 @@ import { StatusPluginBPlugin } from './plugin'; -export const plugin = () => new StatusPluginBPlugin(); +export const plugin = async () => new StatusPluginBPlugin(); diff --git a/tsconfig.base.json b/tsconfig.base.json index f833b70622d32..a92c90b6aeb38 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -832,8 +832,6 @@ "@kbn/generate-console-definitions/*": ["packages/kbn-generate-console-definitions/*"], "@kbn/generate-csv": ["packages/kbn-generate-csv"], "@kbn/generate-csv/*": ["packages/kbn-generate-csv/*"], - "@kbn/generate-csv-types": ["packages/kbn-generate-csv-types"], - "@kbn/generate-csv-types/*": ["packages/kbn-generate-csv-types/*"], "@kbn/get-repo-files": ["packages/kbn-get-repo-files"], "@kbn/get-repo-files/*": ["packages/kbn-get-repo-files/*"], "@kbn/global-search-bar-plugin": ["x-pack/plugins/global_search_bar"], @@ -1178,8 +1176,26 @@ "@kbn/reporting-common/*": ["packages/kbn-reporting/common/*"], "@kbn/reporting-example-plugin": ["x-pack/examples/reporting_example"], "@kbn/reporting-example-plugin/*": ["x-pack/examples/reporting_example/*"], + "@kbn/reporting-export-types-csv": ["packages/kbn-reporting/export_types/csv"], + "@kbn/reporting-export-types-csv/*": ["packages/kbn-reporting/export_types/csv/*"], + "@kbn/reporting-export-types-csv-common": ["packages/kbn-reporting/export_types/csv_common"], + "@kbn/reporting-export-types-csv-common/*": ["packages/kbn-reporting/export_types/csv_common/*"], + "@kbn/reporting-export-types-pdf": ["packages/kbn-reporting/export_types/pdf"], + "@kbn/reporting-export-types-pdf/*": ["packages/kbn-reporting/export_types/pdf/*"], + "@kbn/reporting-export-types-pdf-common": ["packages/kbn-reporting/export_types/pdf_common"], + "@kbn/reporting-export-types-pdf-common/*": ["packages/kbn-reporting/export_types/pdf_common/*"], + "@kbn/reporting-export-types-png": ["packages/kbn-reporting/export_types/png"], + "@kbn/reporting-export-types-png/*": ["packages/kbn-reporting/export_types/png/*"], + "@kbn/reporting-export-types-png-common": ["packages/kbn-reporting/export_types/png_common"], + "@kbn/reporting-export-types-png-common/*": ["packages/kbn-reporting/export_types/png_common/*"], + "@kbn/reporting-mocks-server": ["packages/kbn-reporting/mocks_server"], + "@kbn/reporting-mocks-server/*": ["packages/kbn-reporting/mocks_server/*"], "@kbn/reporting-plugin": ["x-pack/plugins/reporting"], "@kbn/reporting-plugin/*": ["x-pack/plugins/reporting/*"], + "@kbn/reporting-public": ["packages/kbn-reporting/public"], + "@kbn/reporting-public/*": ["packages/kbn-reporting/public/*"], + "@kbn/reporting-server": ["packages/kbn-reporting/server"], + "@kbn/reporting-server/*": ["packages/kbn-reporting/server/*"], "@kbn/resizable-layout": ["packages/kbn-resizable-layout"], "@kbn/resizable-layout/*": ["packages/kbn-resizable-layout/*"], "@kbn/resizable-layout-examples-plugin": ["examples/resizable_layout_examples"], diff --git a/x-pack/examples/alerting_example/server/index.ts b/x-pack/examples/alerting_example/server/index.ts index f14bbe1baac9d..0dbe94868f43a 100644 --- a/x-pack/examples/alerting_example/server/index.ts +++ b/x-pack/examples/alerting_example/server/index.ts @@ -6,6 +6,8 @@ */ import { PluginInitializer } from '@kbn/core/server'; -import { AlertingExamplePlugin } from './plugin'; -export const plugin: PluginInitializer = () => new AlertingExamplePlugin(); +export const plugin: PluginInitializer = async () => { + const { AlertingExamplePlugin } = await import('./plugin'); + return new AlertingExamplePlugin(); +}; diff --git a/x-pack/examples/gen_ai_streaming_response_example/server/index.ts b/x-pack/examples/gen_ai_streaming_response_example/server/index.ts index e85214a01d03d..e745ea8f51c6c 100644 --- a/x-pack/examples/gen_ai_streaming_response_example/server/index.ts +++ b/x-pack/examples/gen_ai_streaming_response_example/server/index.ts @@ -6,7 +6,8 @@ */ import { PluginInitializer } from '@kbn/core/server'; -import { GenAiStreamingResponseExamplePlugin } from './plugin'; -export const plugin: PluginInitializer = () => - new GenAiStreamingResponseExamplePlugin(); +export const plugin: PluginInitializer = async () => { + const { GenAiStreamingResponseExamplePlugin } = await import('./plugin'); + return new GenAiStreamingResponseExamplePlugin(); +}; diff --git a/x-pack/examples/reporting_example/public/containers/main.tsx b/x-pack/examples/reporting_example/public/containers/main.tsx index ee6b8e69fd62d..07d727172b58b 100644 --- a/x-pack/examples/reporting_example/public/containers/main.tsx +++ b/x-pack/examples/reporting_example/public/containers/main.tsx @@ -5,6 +5,12 @@ * 2.0. */ +import { parsePath } from 'history'; +import moment from 'moment'; +import React, { useEffect, useState } from 'react'; +import * as Rx from 'rxjs'; +import { takeWhile } from 'rxjs/operators'; + import { EuiButton, EuiCard, @@ -18,27 +24,20 @@ import { EuiLink, EuiPage, EuiPageBody, - EuiPageSection, EuiPageHeader, + EuiPageSection, EuiPopover, EuiSpacer, EuiText, EuiTitle, } from '@elastic/eui'; import { I18nProvider } from '@kbn/i18n-react'; -import { parsePath } from 'history'; -import moment from 'moment'; -import React, { useEffect, useState } from 'react'; -import { BrowserRouter as Router, useHistory } from 'react-router-dom'; -import * as Rx from 'rxjs'; -import { takeWhile } from 'rxjs/operators'; -import type { ScreenshotModePluginSetup } from '@kbn/screenshot-mode-plugin/public'; -import type { - JobAppParamsPDF, - JobParamsPDFV2, - JobParamsPNGV2, -} from '@kbn/reporting-plugin/common/types'; +import { JobParamsPDFDeprecated, JobParamsPDFV2 } from '@kbn/reporting-export-types-pdf-common'; +import { JobParamsPNGV2 } from '@kbn/reporting-export-types-png-common'; import type { ReportingStart } from '@kbn/reporting-plugin/public'; +import type { ScreenshotModePluginSetup } from '@kbn/screenshot-mode-plugin/public'; +import { BrowserRouter as Router, useHistory } from 'react-router-dom'; + import { REPORTING_EXAMPLE_LOCATOR_ID } from '../../common'; import { useApplicationContext } from '../application_context'; import { ROUTES } from '../constants'; @@ -81,12 +80,14 @@ export const Main = ({ basename, reporting, screenshotMode }: ReportingExampleAp }); }); - const getPDFJobParamsDefault = (): JobAppParamsPDF => { + const getPDFJobParamsDefault = (): JobParamsPDFDeprecated => { return { layout: { id: 'preserve_layout' }, relativeUrls: ['/app/reportingExample#/intended-visualization'], objectType: 'develeloperExample', title: 'Reporting Developer Example', + browserTimezone: 'UTC', + version: '1', }; }; diff --git a/x-pack/examples/reporting_example/tsconfig.json b/x-pack/examples/reporting_example/tsconfig.json index 6b02e36ce0f9e..cb91f89dea013 100644 --- a/x-pack/examples/reporting_example/tsconfig.json +++ b/x-pack/examples/reporting_example/tsconfig.json @@ -25,5 +25,7 @@ "@kbn/i18n-react", "@kbn/utility-types", "@kbn/shared-ux-router", + "@kbn/reporting-export-types-pdf-common", + "@kbn/reporting-export-types-png-common", ] } diff --git a/x-pack/examples/screenshotting_example/server/index.ts b/x-pack/examples/screenshotting_example/server/index.ts index 2d9a1d5fbb25b..a1354eee59af9 100644 --- a/x-pack/examples/screenshotting_example/server/index.ts +++ b/x-pack/examples/screenshotting_example/server/index.ts @@ -5,8 +5,7 @@ * 2.0. */ -import { ScreenshottingExamplePlugin } from './plugin'; - -export function plugin() { +export async function plugin() { + const { ScreenshottingExamplePlugin } = await import('./plugin'); return new ScreenshottingExamplePlugin(); } diff --git a/x-pack/examples/third_party_vis_lens_example/server/index.ts b/x-pack/examples/third_party_vis_lens_example/server/index.ts index cba785e2c3783..ea57af5d4e327 100644 --- a/x-pack/examples/third_party_vis_lens_example/server/index.ts +++ b/x-pack/examples/third_party_vis_lens_example/server/index.ts @@ -6,6 +6,8 @@ */ import { PluginInitializer } from '@kbn/core/server'; -import { ThirdPartyVisLensExamplePlugin } from './plugin'; -export const plugin: PluginInitializer = () => new ThirdPartyVisLensExamplePlugin(); +export const plugin: PluginInitializer = async () => { + const { ThirdPartyVisLensExamplePlugin } = await import('./plugin'); + return new ThirdPartyVisLensExamplePlugin(); +}; diff --git a/x-pack/packages/kbn-elastic-assistant/impl/new_chat_by_id/index.test.tsx b/x-pack/packages/kbn-elastic-assistant/impl/new_chat_by_id/index.test.tsx index 7ff86b7631078..f8b1a81387b17 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/new_chat_by_id/index.test.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/new_chat_by_id/index.test.tsx @@ -63,6 +63,15 @@ describe('NewChatById', () => { expect(newChatButton.querySelector('.euiButtonContent__icon')).not.toBeInTheDocument(); }); + it('renders button icon when iconOnly is true', async () => { + render(); + + const newChatButton = screen.getByTestId('newChatById'); + + expect(newChatButton.querySelector('[data-euiicon-type="discuss"]')).toBeInTheDocument(); + expect(newChatButton.textContent).not.toContain('Chat'); + }); + it('calls showAssistantOverlay on click', () => { const conversationId = 'test-conversation-id'; const promptContextId = 'test-prompt-context-id'; diff --git a/x-pack/packages/kbn-elastic-assistant/impl/new_chat_by_id/index.tsx b/x-pack/packages/kbn-elastic-assistant/impl/new_chat_by_id/index.tsx index 721d40118695a..092e48d6f0bfd 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/new_chat_by_id/index.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/new_chat_by_id/index.tsx @@ -5,7 +5,7 @@ * 2.0. */ -import { EuiButtonEmpty } from '@elastic/eui'; +import { EuiButtonEmpty, EuiButtonIcon, EuiToolTip } from '@elastic/eui'; import React, { useCallback, useMemo } from 'react'; import { useAssistantContext } from '../assistant_context'; @@ -20,6 +20,8 @@ export interface Props { iconType?: string | null; /** Optionally specify a well known ID, or default to a UUID */ promptContextId?: string; + /** Defaults to false. If true, shows icon button without text */ + iconOnly?: boolean; } const NewChatByIdComponent: React.FC = ({ @@ -27,6 +29,7 @@ const NewChatByIdComponent: React.FC = ({ conversationId, iconType, promptContextId, + iconOnly = false, }) => { const { showAssistantOverlay } = useAssistantContext(); @@ -50,12 +53,28 @@ const NewChatByIdComponent: React.FC = ({ }, [iconType]); return useMemo( - () => ( - - {children} - - ), - [children, icon, showOverlay] + () => + iconOnly ? ( + + + + ) : ( + + {children} + + ), + [children, icon, showOverlay, iconOnly] ); }; diff --git a/x-pack/packages/ml/response_stream/server/index.ts b/x-pack/packages/ml/response_stream/server/index.ts index 820c76d173c74..2beb722302617 100644 --- a/x-pack/packages/ml/response_stream/server/index.ts +++ b/x-pack/packages/ml/response_stream/server/index.ts @@ -5,4 +5,8 @@ * 2.0. */ -export { streamFactory } from './stream_factory'; +export { + streamFactory, + type StreamFactoryReturnType, + type UncompressedResponseStream, +} from './stream_factory'; diff --git a/x-pack/packages/ml/response_stream/server/stream_factory.ts b/x-pack/packages/ml/response_stream/server/stream_factory.ts index 8836c241e55d8..29c570c2fb564 100644 --- a/x-pack/packages/ml/response_stream/server/stream_factory.ts +++ b/x-pack/packages/ml/response_stream/server/stream_factory.ts @@ -22,13 +22,13 @@ function isCompressedSream(arg: unknown): arg is zlib.Gzip { const FLUSH_KEEP_ALIVE_INTERVAL_MS = 500; const FLUSH_PAYLOAD_SIZE = 4 * 1024; -class UncompressedResponseStream extends Stream.PassThrough {} +export class UncompressedResponseStream extends Stream.PassThrough {} const DELIMITER = '\n'; type StreamType = 'string' | 'ndjson'; -interface StreamFactoryReturnType { +export interface StreamFactoryReturnType { DELIMITER: string; end: () => void; push: (d: T, drain?: boolean) => void; diff --git a/x-pack/plugins/actions/server/index.ts b/x-pack/plugins/actions/server/index.ts index a82ec2fd1ce4a..39b94204520b7 100644 --- a/x-pack/plugins/actions/server/index.ts +++ b/x-pack/plugins/actions/server/index.ts @@ -7,7 +7,6 @@ import { get } from 'lodash'; import type { PublicMethodsOf } from '@kbn/utility-types'; import { PluginInitializerContext, PluginConfigDescriptor } from '@kbn/core/server'; -import { ActionsPlugin } from './plugin'; import { configSchema, ActionsConfig, CustomHostSettings } from './config'; import { ActionsClient as ActionsClientClass } from './actions_client'; import { ActionsAuthorization as ActionsAuthorizationClass } from './authorization/actions_authorization'; @@ -37,7 +36,10 @@ export { } from './lib'; export { ACTION_SAVED_OBJECT_TYPE } from './constants/saved_objects'; -export const plugin = (initContext: PluginInitializerContext) => new ActionsPlugin(initContext); +export const plugin = async (initContext: PluginInitializerContext) => { + const { ActionsPlugin } = await import('./plugin'); + return new ActionsPlugin(initContext); +}; export { SubActionConnector } from './sub_action_framework/sub_action_connector'; export { CaseConnector } from './sub_action_framework/case'; diff --git a/x-pack/plugins/actions/server/lib/action_executor.ts b/x-pack/plugins/actions/server/lib/action_executor.ts index 52f995fdd9eb7..b27e2c1ee79c7 100644 --- a/x-pack/plugins/actions/server/lib/action_executor.ts +++ b/x-pack/plugins/actions/server/lib/action_executor.ts @@ -338,7 +338,7 @@ export class ActionExecutor { }) .then((tokenTracking) => { if (tokenTracking != null) { - set(event, 'kibana.action.execution.get_ai.usage', { + set(event, 'kibana.action.execution.gen_ai.usage', { total_tokens: tokenTracking.total_tokens, prompt_tokens: tokenTracking.prompt_tokens, completion_tokens: tokenTracking.completion_tokens, 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 7a0fe12553e97..22f91b71d4492 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 @@ -5,7 +5,7 @@ * 2.0. */ -import { getGenAiTokenTracking } from './gen_ai_token_tracking'; +import { getGenAiTokenTracking, shouldTrackGenAiToken } from './gen_ai_token_tracking'; import { loggerMock } from '@kbn/logging-mocks'; import { getTokenCountFromBedrockInvoke } from './get_token_count_from_bedrock_invoke'; import { getTokenCountFromInvokeStream } from './get_token_count_from_invoke_stream'; @@ -168,4 +168,16 @@ describe('getGenAiTokenTracking', () => { expect(tokenTracking).toBeNull(); expect(logger.error).toHaveBeenCalled(); }); + + describe('shouldTrackGenAiToken', () => { + it('should be true with OpenAI action', () => { + expect(shouldTrackGenAiToken('.gen-ai')).toEqual(true); + }); + it('should be true with bedrock action', () => { + expect(shouldTrackGenAiToken('.bedrock')).toEqual(true); + }); + it('should be false with any other action', () => { + expect(shouldTrackGenAiToken('.jira')).toEqual(false); + }); + }); }); 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 f39f539a1ad5c..7c104177ea36e 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 @@ -43,6 +43,7 @@ export const getGenAiTokenTracking = async ({ const { total, prompt, completion } = await getTokenCountFromInvokeStream({ responseStream: result.data.pipe(new PassThrough()), body: (validatedParams as { subActionParams: InvokeBody }).subActionParams, + logger, }); return { total_tokens: total, @@ -61,6 +62,7 @@ export const getGenAiTokenTracking = async ({ const { total, prompt, completion } = await getTokenCountFromOpenAIStream({ responseStream: result.data.pipe(new PassThrough()), body: (validatedParams as { subActionParams: { body: string } }).subActionParams.body, + logger, }); return { total_tokens: total, 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 de6f4a20aca5b..3c0dd66130f3a 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 @@ -6,6 +6,7 @@ */ import { Transform } from 'stream'; import { getTokenCountFromInvokeStream } from './get_token_count_from_invoke_stream'; +import { loggerMock } from '@kbn/logging-mocks'; interface StreamMock { write: (data: string) => void; @@ -31,7 +32,7 @@ function createStreamMock(): StreamMock { }, }; } - +const logger = loggerMock.create(); describe('getTokenCountFromInvokeStream', () => { let stream: StreamMock; const body = { @@ -63,6 +64,7 @@ describe('getTokenCountFromInvokeStream', () => { const tokens = await getTokenCountFromInvokeStream({ responseStream: stream.transform, body, + logger, }); expect(tokens.prompt).toBe(PROMPT_TOKEN_COUNT); expect(tokens.completion).toBe(COMPLETION_TOKEN_COUNT); @@ -75,6 +77,7 @@ describe('getTokenCountFromInvokeStream', () => { const tokenPromise = getTokenCountFromInvokeStream({ responseStream: stream.transform, body, + logger, }); stream.fail(); @@ -84,6 +87,7 @@ describe('getTokenCountFromInvokeStream', () => { total: PROMPT_TOKEN_COUNT + COMPLETION_TOKEN_COUNT, completion: COMPLETION_TOKEN_COUNT, }); + expect(logger.error).toHaveBeenCalled(); }); }); }); 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 009a8f8957bed..594fec89d93c0 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 @@ -5,6 +5,7 @@ * 2.0. */ +import { Logger } from '@kbn/logging'; import { encode } from 'gpt-tokenizer'; import { Readable } from 'stream'; import { finished } from 'stream/promises'; @@ -22,13 +23,16 @@ export interface InvokeBody { * Returns an object containing the total, prompt, and completion token counts. * @param responseStream the response stream from the `invokeStream` sub action * @param body the request messages array + * @param logger the logger */ export async function getTokenCountFromInvokeStream({ responseStream, body, + logger, }: { responseStream: Readable; body: InvokeBody; + logger: Logger; }): Promise<{ total: number; prompt: number; @@ -48,8 +52,11 @@ export async function getTokenCountFromInvokeStream({ responseStream.on('data', (chunk: string) => { responseBody += chunk.toString(); }); - - await finished(responseStream); + try { + await finished(responseStream); + } catch (e) { + logger.error('An error occurred while calculating streaming response tokens'); + } const completionTokens = encode(responseBody).length; diff --git a/x-pack/plugins/actions/server/lib/get_token_count_from_openai_stream.test.ts b/x-pack/plugins/actions/server/lib/get_token_count_from_openai_stream.test.ts index 080b7cb5f972f..cc81706fc257c 100644 --- a/x-pack/plugins/actions/server/lib/get_token_count_from_openai_stream.test.ts +++ b/x-pack/plugins/actions/server/lib/get_token_count_from_openai_stream.test.ts @@ -6,6 +6,7 @@ */ import { Transform } from 'stream'; import { getTokenCountFromOpenAIStream } from './get_token_count_from_openai_stream'; +import { loggerMock } from '@kbn/logging-mocks'; interface StreamMock { write: (data: string) => void; @@ -32,6 +33,7 @@ function createStreamMock(): StreamMock { }; } +const logger = loggerMock.create(); describe('getTokenCountFromOpenAIStream', () => { let tokens: Awaited>; let stream: StreamMock; @@ -77,6 +79,7 @@ describe('getTokenCountFromOpenAIStream', () => { beforeEach(async () => { tokens = await getTokenCountFromOpenAIStream({ responseStream: stream.transform, + logger, body: JSON.stringify(body), }); }); @@ -92,6 +95,7 @@ describe('getTokenCountFromOpenAIStream', () => { beforeEach(async () => { tokens = await getTokenCountFromOpenAIStream({ responseStream: stream.transform, + logger, body: JSON.stringify({ ...body, functions: [ @@ -123,6 +127,7 @@ describe('getTokenCountFromOpenAIStream', () => { it('resolves the promise with the correct prompt tokens', async () => { const tokenPromise = getTokenCountFromOpenAIStream({ responseStream: stream.transform, + logger, body: JSON.stringify(body), }); @@ -133,6 +138,7 @@ describe('getTokenCountFromOpenAIStream', () => { total: PROMPT_TOKEN_COUNT + COMPLETION_TOKEN_COUNT, completion: COMPLETION_TOKEN_COUNT, }); + expect(logger.error).toHaveBeenCalled(); }); }); }); diff --git a/x-pack/plugins/actions/server/lib/get_token_count_from_openai_stream.ts b/x-pack/plugins/actions/server/lib/get_token_count_from_openai_stream.ts index 1463a56ccc35c..0091faca468e3 100644 --- a/x-pack/plugins/actions/server/lib/get_token_count_from_openai_stream.ts +++ b/x-pack/plugins/actions/server/lib/get_token_count_from_openai_stream.ts @@ -10,13 +10,16 @@ import { isEmpty, omitBy } from 'lodash'; import { Readable } from 'stream'; import { finished } from 'stream/promises'; import { CreateChatCompletionRequest } from 'openai'; +import { Logger } from '@kbn/logging'; export async function getTokenCountFromOpenAIStream({ responseStream, body, + logger, }: { responseStream: Readable; body: string; + logger: Logger; }): Promise<{ total: number; prompt: number; @@ -63,7 +66,11 @@ export async function getTokenCountFromOpenAIStream({ responseBody += chunk.toString(); }); - await finished(responseStream); + try { + await finished(responseStream); + } catch (e) { + logger.error('An error occurred while calculating streaming response tokens'); + } const response = responseBody .split('\n') diff --git a/x-pack/plugins/actions/server/lib/request_oauth_client_credentials_token.test.ts b/x-pack/plugins/actions/server/lib/request_oauth_client_credentials_token.test.ts index 223c8c28b55bc..fa5be0e332330 100644 --- a/x-pack/plugins/actions/server/lib/request_oauth_client_credentials_token.test.ts +++ b/x-pack/plugins/actions/server/lib/request_oauth_client_credentials_token.test.ts @@ -123,7 +123,7 @@ describe('requestOAuthClientCredentialsToken', () => { expect(mockLogger.warn.mock.calls[0]).toMatchInlineSnapshot(` Array [ - "error thrown getting the access token from https://test for params: {\\"scope\\":\\"test\\",\\"client_id\\":\\"123456\\",\\"client_secret\\":\\"secrert123\\"}: {\\"error\\":\\"invalid_scope\\",\\"error_description\\":\\"AADSTS70011: The provided value for the input parameter 'scope' is not valid.\\"}", + "error thrown getting the access token from https://test: {\\"error\\":\\"invalid_scope\\",\\"error_description\\":\\"AADSTS70011: The provided value for the input parameter 'scope' is not valid.\\"}", ] `); }); diff --git a/x-pack/plugins/actions/server/lib/request_oauth_jwt_token.test.ts b/x-pack/plugins/actions/server/lib/request_oauth_jwt_token.test.ts index af65bcf67d3db..c096212af440e 100644 --- a/x-pack/plugins/actions/server/lib/request_oauth_jwt_token.test.ts +++ b/x-pack/plugins/actions/server/lib/request_oauth_jwt_token.test.ts @@ -125,7 +125,7 @@ describe('requestOAuthJWTToken', () => { expect(mockLogger.warn.mock.calls[0]).toMatchInlineSnapshot(` Array [ - "error thrown getting the access token from https://test for params: {\\"assertion\\":\\"someJWTvalueishere\\",\\"scope\\":\\"test\\",\\"client_id\\":\\"client-id-1\\",\\"client_secret\\":\\"some-client-secret\\"}: {\\"error\\":\\"invalid_scope\\",\\"error_description\\":\\"AADSTS70011: The provided value for the input parameter 'scope' is not valid.\\"}", + "error thrown getting the access token from https://test: {\\"error\\":\\"invalid_scope\\",\\"error_description\\":\\"AADSTS70011: The provided value for the input parameter 'scope' is not valid.\\"}", ] `); }); diff --git a/x-pack/plugins/actions/server/lib/request_oauth_token.test.ts b/x-pack/plugins/actions/server/lib/request_oauth_token.test.ts index 9843783aadf8d..cc7d6d5e4822d 100644 --- a/x-pack/plugins/actions/server/lib/request_oauth_token.test.ts +++ b/x-pack/plugins/actions/server/lib/request_oauth_token.test.ts @@ -132,7 +132,7 @@ describe('requestOAuthToken', () => { expect(mockLogger.warn.mock.calls[0]).toMatchInlineSnapshot(` Array [ - "error thrown getting the access token from https://test for params: {\\"client_id\\":\\"123456\\",\\"client_secret\\":\\"secrert123\\",\\"some_additional_param\\":\\"test\\"}: {\\"error\\":\\"invalid_scope\\",\\"error_description\\":\\"AADSTS70011: The provided value for the input parameter 'scope' is not valid.\\"}", + "error thrown getting the access token from https://test: {\\"error\\":\\"invalid_scope\\",\\"error_description\\":\\"AADSTS70011: The provided value for the input parameter 'scope' is not valid.\\"}", ] `); }); diff --git a/x-pack/plugins/actions/server/lib/request_oauth_token.ts b/x-pack/plugins/actions/server/lib/request_oauth_token.ts index 116d3f2cc3315..ab62dd726f7a8 100644 --- a/x-pack/plugins/actions/server/lib/request_oauth_token.ts +++ b/x-pack/plugins/actions/server/lib/request_oauth_token.ts @@ -52,11 +52,7 @@ export async function requestOAuthToken( }; } else { const errString = stringify(res.data); - logger.warn( - `error thrown getting the access token from ${tokenUrl} for params: ${JSON.stringify( - bodyRequest - )}: ${errString}` - ); + logger.warn(`error thrown getting the access token from ${tokenUrl}: ${errString}`); throw new Error(errString); } } diff --git a/x-pack/plugins/aiops/README.md b/x-pack/plugins/aiops/README.md index 2d07e0c34653a..2ea2a315c594f 100755 --- a/x-pack/plugins/aiops/README.md +++ b/x-pack/plugins/aiops/README.md @@ -4,6 +4,16 @@ The plugin provides APIs and components for AIOps features, including the “Log --- +## Log Rate Analysis + +Here's some notes on the structure of the code for the API endpoint `/internal/aiops/log_rate_analysis`. The endpoint uses the `@kbn/ml-response-stream` package to return the request's response as a HTTP stream of JSON objects. The files are located in `x-pack/plugins/aiops/server/routes/log_rate_analysis/`. + +`define_route.ts:defineRoute()` is the outer most wrapper that's used to define the route and its versions. It calls `route_handler_factory:routeHandlerFactory()` for each version. + +The route handler sets up `response_stream_factory:responseStreamFactory()` to create the response stream and then walks through the steps of the analysis. + +The response stream factory acts as a wrapper to set up the stream itself, the stream state (for example to set if it's running etc.), some custom actions on the stream as well as analysis handlers that fetch data from ES and pass it on to the stream. + ## Development See the [kibana contributing guide](https://github.com/elastic/kibana/blob/main/CONTRIBUTING.md) for instructions setting up your development environment. 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 0770cfea83771..0ce422a0fb872 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 @@ -5,7 +5,8 @@ * 2.0. */ -import React, { useEffect, useState, type FC } from 'react'; +import { isEqual } from 'lodash'; +import React, { useEffect, useMemo, useState, type FC } from 'react'; import { EuiEmptyPrompt, EuiHorizontalRule, EuiPanel } from '@elastic/eui'; import type { Moment } from 'moment'; @@ -32,7 +33,18 @@ import { import type { GroupTableItem } from '../../log_rate_analysis_results_table/types'; import { useLogRateAnalysisResultsTableRowContext } from '../../log_rate_analysis_results_table/log_rate_analysis_results_table_row_provider'; -const DEFAULT_SEARCH_QUERY = { match_all: {} }; +const DEFAULT_SEARCH_QUERY: estypes.QueryDslQueryContainer = { match_all: {} }; +const DEFAULT_SEARCH_BAR_QUERY: estypes.QueryDslQueryContainer = { + bool: { + filter: [], + must: [ + { + match_all: {}, + }, + ], + must_not: [], + }, +}; export function getDocumentCountStatsSplitLabel( significantItem?: SignificantItem, @@ -93,6 +105,13 @@ export const LogRateAnalysisContent: FC = ({ setIsBrushCleared(windowParameters === undefined); }, [windowParameters]); + // Checks if `esSearchQuery` is the default empty query passed on from the search bar + // and if that's the case fall back to a simpler match all query. + const searchQuery = useMemo( + () => (isEqual(esSearchQuery, DEFAULT_SEARCH_BAR_QUERY) ? DEFAULT_SEARCH_QUERY : esSearchQuery), + [esSearchQuery] + ); + const { currentSelectedSignificantItem, currentSelectedGroup, @@ -105,7 +124,7 @@ export const LogRateAnalysisContent: FC = ({ const { documentStats, earliest, latest } = useData( dataView, 'log_rate_analysis', - esSearchQuery, + searchQuery, setGlobalState, currentSelectedSignificantItem, currentSelectedGroup, @@ -170,7 +189,7 @@ export const LogRateAnalysisContent: FC = ({ stickyHistogram={stickyHistogram} onReset={clearSelection} sampleProbability={sampleProbability} - searchQuery={esSearchQuery} + searchQuery={searchQuery} windowParameters={windowParameters} barColorOverride={barColorOverride} barHighlightColorOverride={barHighlightColorOverride} diff --git a/x-pack/plugins/aiops/server/index.ts b/x-pack/plugins/aiops/server/index.ts index 8dca6eb397d5e..e6b1dace67029 100755 --- a/x-pack/plugins/aiops/server/index.ts +++ b/x-pack/plugins/aiops/server/index.ts @@ -6,9 +6,9 @@ */ import { PluginInitializerContext } from '@kbn/core/server'; -import { AiopsPlugin } from './plugin'; -export function plugin(initializerContext: PluginInitializerContext) { +export async function plugin(initializerContext: PluginInitializerContext) { + const { AiopsPlugin } = await import('./plugin'); return new AiopsPlugin(initializerContext); } diff --git a/x-pack/plugins/aiops/server/routes/log_rate_analysis/analysis_handlers/grouping_handler.ts b/x-pack/plugins/aiops/server/routes/log_rate_analysis/analysis_handlers/grouping_handler.ts new file mode 100644 index 0000000000000..e725d25bbe01f --- /dev/null +++ b/x-pack/plugins/aiops/server/routes/log_rate_analysis/analysis_handlers/grouping_handler.ts @@ -0,0 +1,247 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { queue } from 'async'; + +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; + +import { KBN_FIELD_TYPES } from '@kbn/field-types'; +import { i18n } from '@kbn/i18n'; +import { + fetchHistogramsForFields, + type SignificantItem, + type SignificantItemGroup, + type SignificantItemHistogramItem, + type NumericChartData, +} from '@kbn/ml-agg-utils'; + +import { RANDOM_SAMPLER_SEED } from '../../../../common/constants'; +import { + addSignificantItemsGroupAction, + addSignificantItemsGroupHistogramAction, + updateLoadingStateAction, +} from '../../../../common/api/log_rate_analysis/actions'; +import type { AiopsLogRateAnalysisApiVersion as ApiVersion } from '../../../../common/api/log_rate_analysis/schema'; + +import { isRequestAbortedError } from '../../../lib/is_request_aborted_error'; + +import { fetchFrequentItemSets } from '../queries/fetch_frequent_item_sets'; +import { fetchTerms2CategoriesCounts } from '../queries/fetch_terms_2_categories_counts'; +import { getGroupFilter } from '../queries/get_group_filter'; +import { getHistogramQuery } from '../queries/get_histogram_query'; +import { getSignificantItemGroups } from '../queries/get_significant_item_groups'; + +import { MAX_CONCURRENT_QUERIES, PROGRESS_STEP_GROUPING } from '../response_stream_utils/constants'; +import type { ResponseStreamFetchOptions } from '../response_stream_factory'; + +export const groupingHandlerFactory = + ({ + abortSignal, + client, + requestBody, + responseStream, + logDebugMessage, + logger, + stateHandler, + version, + }: ResponseStreamFetchOptions) => + async ( + significantCategories: SignificantItem[], + significantTerms: SignificantItem[], + overallTimeSeries?: NumericChartData + ) => { + logDebugMessage('Group results.'); + + function pushHistogramDataLoadingState() { + responseStream.push( + updateLoadingStateAction({ + ccsWarning: false, + loaded: stateHandler.loaded(), + loadingState: i18n.translate( + 'xpack.aiops.logRateAnalysis.loadingState.loadingHistogramData', + { + defaultMessage: 'Loading histogram data.', + } + ), + }) + ); + } + + responseStream.push( + updateLoadingStateAction({ + ccsWarning: false, + loaded: stateHandler.loaded(), + loadingState: i18n.translate('xpack.aiops.logRateAnalysis.loadingState.groupingResults', { + defaultMessage: 'Transforming significant field/value pairs into groups.', + }), + groupsMissing: true, + }) + ); + + try { + const { fields, itemSets } = await fetchFrequentItemSets( + client, + requestBody.index, + JSON.parse(requestBody.searchQuery) as estypes.QueryDslQueryContainer, + significantTerms, + requestBody.timeFieldName, + requestBody.deviationMin, + requestBody.deviationMax, + logger, + stateHandler.sampleProbability(), + responseStream.pushError, + abortSignal + ); + + if (significantCategories.length > 0 && significantTerms.length > 0) { + const { fields: significantCategoriesFields, itemSets: significantCategoriesItemSets } = + await fetchTerms2CategoriesCounts( + client, + requestBody, + JSON.parse(requestBody.searchQuery) as estypes.QueryDslQueryContainer, + significantTerms, + itemSets, + significantCategories, + requestBody.deviationMin, + requestBody.deviationMax, + logger, + responseStream.pushError, + abortSignal + ); + + fields.push(...significantCategoriesFields); + itemSets.push(...significantCategoriesItemSets); + } + + if (stateHandler.shouldStop()) { + logDebugMessage('shouldStop after fetching frequent_item_sets.'); + responseStream.end(); + return; + } + + if (fields.length > 0 && itemSets.length > 0) { + const significantItemGroups = getSignificantItemGroups( + itemSets, + [...significantTerms, ...significantCategories], + fields + ); + + // We'll find out if there's at least one group with at least two items, + // only then will we return the groups to the clients and make the grouping option available. + const maxItems = Math.max(...significantItemGroups.map((g) => g.group.length)); + + if (maxItems > 1) { + responseStream.push(addSignificantItemsGroupAction(significantItemGroups, version)); + } + + stateHandler.loaded(PROGRESS_STEP_GROUPING, false); + pushHistogramDataLoadingState(); + + if (stateHandler.shouldStop()) { + logDebugMessage('shouldStop after grouping.'); + responseStream.end(); + return; + } + + logDebugMessage(`Fetch ${significantItemGroups.length} group histograms.`); + + const groupHistogramQueue = queue(async function (cpg: SignificantItemGroup) { + if (stateHandler.shouldStop()) { + logDebugMessage('shouldStop abort fetching group histograms.'); + groupHistogramQueue.kill(); + responseStream.end(); + return; + } + + if (overallTimeSeries !== undefined) { + const histogramQuery = getHistogramQuery(requestBody, getGroupFilter(cpg)); + + let cpgTimeSeries: NumericChartData; + try { + cpgTimeSeries = ( + (await fetchHistogramsForFields( + client, + requestBody.index, + histogramQuery, + // fields + [ + { + fieldName: requestBody.timeFieldName, + type: KBN_FIELD_TYPES.DATE, + interval: overallTimeSeries.interval, + min: overallTimeSeries.stats[0], + max: overallTimeSeries.stats[1], + }, + ], + // samplerShardSize + -1, + undefined, + abortSignal, + stateHandler.sampleProbability(), + RANDOM_SAMPLER_SEED + )) as [NumericChartData] + )[0]; + } catch (e) { + if (!isRequestAbortedError(e)) { + logger.error( + `Failed to fetch the histogram data for group #${cpg.id}, got: \n${e.toString()}` + ); + responseStream.pushError( + `Failed to fetch the histogram data for group #${cpg.id}.` + ); + } + return; + } + const histogram: SignificantItemHistogramItem[] = + overallTimeSeries.data.map((o) => { + const current = cpgTimeSeries.data.find( + (d1) => d1.key_as_string === o.key_as_string + ) ?? { + doc_count: 0, + }; + + if (version === '1') { + return { + key: o.key, + key_as_string: o.key_as_string ?? '', + doc_count_significant_term: current.doc_count, + doc_count_overall: Math.max(0, o.doc_count - current.doc_count), + }; + } + + return { + key: o.key, + key_as_string: o.key_as_string ?? '', + doc_count_significant_item: current.doc_count, + doc_count_overall: Math.max(0, o.doc_count - current.doc_count), + }; + }) ?? []; + + responseStream.push( + addSignificantItemsGroupHistogramAction( + [ + { + id: cpg.id, + histogram, + }, + ], + version + ) + ); + } + }, MAX_CONCURRENT_QUERIES); + + groupHistogramQueue.push(significantItemGroups); + await groupHistogramQueue.drain(); + } + } catch (e) { + if (!isRequestAbortedError(e)) { + logger.error(`Failed to transform field/value pairs into groups, got: \n${e.toString()}`); + responseStream.pushError(`Failed to transform field/value pairs into groups.`); + } + } + }; diff --git a/x-pack/plugins/aiops/server/routes/log_rate_analysis/analysis_handlers/histogram_handler.ts b/x-pack/plugins/aiops/server/routes/log_rate_analysis/analysis_handlers/histogram_handler.ts new file mode 100644 index 0000000000000..1ddb624c99056 --- /dev/null +++ b/x-pack/plugins/aiops/server/routes/log_rate_analysis/analysis_handlers/histogram_handler.ts @@ -0,0 +1,275 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { queue } from 'async'; + +import { i18n } from '@kbn/i18n'; +import { KBN_FIELD_TYPES } from '@kbn/field-types'; +import type { + SignificantItem, + SignificantItemHistogramItem, + NumericChartData, +} from '@kbn/ml-agg-utils'; +import { fetchHistogramsForFields } from '@kbn/ml-agg-utils'; + +import { RANDOM_SAMPLER_SEED } from '../../../../common/constants'; +import { + addSignificantItemsHistogramAction, + updateLoadingStateAction, +} from '../../../../common/api/log_rate_analysis/actions'; +import type { AiopsLogRateAnalysisApiVersion as ApiVersion } from '../../../../common/api/log_rate_analysis/schema'; +import { getCategoryQuery } from '../../../../common/api/log_categorization/get_category_query'; + +import { getHistogramQuery } from '../queries/get_histogram_query'; + +import { + MAX_CONCURRENT_QUERIES, + PROGRESS_STEP_HISTOGRAMS, +} from '../response_stream_utils/constants'; +import type { ResponseStreamFetchOptions } from '../response_stream_factory'; + +export const histogramHandlerFactory = + ({ + abortSignal, + client, + logDebugMessage, + logger, + requestBody, + responseStream, + stateHandler, + version, + }: ResponseStreamFetchOptions) => + async ( + fieldValuePairsCount: number, + significantCategories: SignificantItem[], + significantTerms: SignificantItem[], + overallTimeSeries?: NumericChartData + ) => { + function pushHistogramDataLoadingState() { + responseStream.push( + updateLoadingStateAction({ + ccsWarning: false, + loaded: stateHandler.loaded(), + loadingState: i18n.translate( + 'xpack.aiops.logRateAnalysis.loadingState.loadingHistogramData', + { + defaultMessage: 'Loading histogram data.', + } + ), + }) + ); + } + + logDebugMessage(`Fetch ${significantTerms.length} field/value histograms.`); + + // time series filtered by fields + if ( + significantTerms.length > 0 && + overallTimeSeries !== undefined && + !requestBody.overrides?.regroupOnly + ) { + const fieldValueHistogramQueue = queue(async function (cp: SignificantItem) { + if (stateHandler.shouldStop()) { + logDebugMessage('shouldStop abort fetching field/value histograms.'); + fieldValueHistogramQueue.kill(); + responseStream.end(); + return; + } + + if (overallTimeSeries !== undefined) { + const histogramQuery = getHistogramQuery(requestBody, [ + { + term: { [cp.fieldName]: cp.fieldValue }, + }, + ]); + + let cpTimeSeries: NumericChartData; + + try { + cpTimeSeries = ( + (await fetchHistogramsForFields( + client, + requestBody.index, + histogramQuery, + // fields + [ + { + fieldName: requestBody.timeFieldName, + type: KBN_FIELD_TYPES.DATE, + interval: overallTimeSeries.interval, + min: overallTimeSeries.stats[0], + max: overallTimeSeries.stats[1], + }, + ], + // samplerShardSize + -1, + undefined, + abortSignal, + stateHandler.sampleProbability(), + RANDOM_SAMPLER_SEED + )) as [NumericChartData] + )[0]; + } catch (e) { + logger.error( + `Failed to fetch the histogram data for field/value pair "${cp.fieldName}:${ + cp.fieldValue + }", got: \n${e.toString()}` + ); + responseStream.pushError( + `Failed to fetch the histogram data for field/value pair "${cp.fieldName}:${cp.fieldValue}".` + ); + return; + } + + const histogram: SignificantItemHistogramItem[] = + overallTimeSeries.data.map((o) => { + const current = cpTimeSeries.data.find( + (d1) => d1.key_as_string === o.key_as_string + ) ?? { + doc_count: 0, + }; + if (version === '1') { + return { + key: o.key, + key_as_string: o.key_as_string ?? '', + doc_count_significant_term: current.doc_count, + doc_count_overall: Math.max(0, o.doc_count - current.doc_count), + }; + } + + return { + key: o.key, + key_as_string: o.key_as_string ?? '', + doc_count_significant_item: current.doc_count, + doc_count_overall: Math.max(0, o.doc_count - current.doc_count), + }; + }) ?? []; + + const { fieldName, fieldValue } = cp; + + stateHandler.loaded((1 / fieldValuePairsCount) * PROGRESS_STEP_HISTOGRAMS, false); + pushHistogramDataLoadingState(); + responseStream.push( + addSignificantItemsHistogramAction( + [ + { + fieldName, + fieldValue, + histogram, + }, + ], + version + ) + ); + } + }, MAX_CONCURRENT_QUERIES); + + fieldValueHistogramQueue.push(significantTerms); + await fieldValueHistogramQueue.drain(); + } + + // histograms for text field patterns + if ( + overallTimeSeries !== undefined && + significantCategories.length > 0 && + !requestBody.overrides?.regroupOnly + ) { + const significantCategoriesHistogramQueries = significantCategories.map((d) => { + const histogramQuery = getHistogramQuery(requestBody); + const categoryQuery = getCategoryQuery(d.fieldName, [ + { key: `${d.key}`, count: d.doc_count, examples: [] }, + ]); + if (Array.isArray(histogramQuery.bool?.filter)) { + histogramQuery.bool?.filter?.push(categoryQuery); + } + return histogramQuery; + }); + + for (const [i, histogramQuery] of significantCategoriesHistogramQueries.entries()) { + const cp = significantCategories[i]; + let catTimeSeries: NumericChartData; + + try { + catTimeSeries = ( + (await fetchHistogramsForFields( + client, + requestBody.index, + histogramQuery, + // fields + [ + { + fieldName: requestBody.timeFieldName, + type: KBN_FIELD_TYPES.DATE, + interval: overallTimeSeries.interval, + min: overallTimeSeries.stats[0], + max: overallTimeSeries.stats[1], + }, + ], + // samplerShardSize + -1, + undefined, + abortSignal, + stateHandler.sampleProbability(), + RANDOM_SAMPLER_SEED + )) as [NumericChartData] + )[0]; + } catch (e) { + logger.error( + `Failed to fetch the histogram data for field/value pair "${cp.fieldName}:${ + cp.fieldValue + }", got: \n${e.toString()}` + ); + responseStream.pushError( + `Failed to fetch the histogram data for field/value pair "${cp.fieldName}:${cp.fieldValue}".` + ); + return; + } + + const histogram: SignificantItemHistogramItem[] = + overallTimeSeries.data.map((o) => { + const current = catTimeSeries.data.find( + (d1) => d1.key_as_string === o.key_as_string + ) ?? { + doc_count: 0, + }; + + if (version === '1') { + return { + key: o.key, + key_as_string: o.key_as_string ?? '', + doc_count_significant_term: current.doc_count, + doc_count_overall: Math.max(0, o.doc_count - current.doc_count), + }; + } + + return { + key: o.key, + key_as_string: o.key_as_string ?? '', + doc_count_significant_item: current.doc_count, + doc_count_overall: Math.max(0, o.doc_count - current.doc_count), + }; + }) ?? []; + + const { fieldName, fieldValue } = cp; + + stateHandler.loaded((1 / fieldValuePairsCount) * PROGRESS_STEP_HISTOGRAMS, false); + pushHistogramDataLoadingState(); + responseStream.push( + addSignificantItemsHistogramAction( + [ + { + fieldName, + fieldValue, + histogram, + }, + ], + version + ) + ); + } + } + }; diff --git a/x-pack/plugins/aiops/server/routes/log_rate_analysis/analysis_handlers/index_info_handler.ts b/x-pack/plugins/aiops/server/routes/log_rate_analysis/analysis_handlers/index_info_handler.ts new file mode 100644 index 0000000000000..6ae2a07055aec --- /dev/null +++ b/x-pack/plugins/aiops/server/routes/log_rate_analysis/analysis_handlers/index_info_handler.ts @@ -0,0 +1,109 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { i18n } from '@kbn/i18n'; + +import { updateLoadingStateAction } from '../../../../common/api/log_rate_analysis/actions'; +import type { AiopsLogRateAnalysisApiVersion as ApiVersion } from '../../../../common/api/log_rate_analysis/schema'; + +import { isRequestAbortedError } from '../../../lib/is_request_aborted_error'; + +import { fetchIndexInfo } from '../queries/fetch_index_info'; + +import type { ResponseStreamFetchOptions } from '../response_stream_factory'; +import { LOADED_FIELD_CANDIDATES } from '../response_stream_utils/constants'; + +export const indexInfoHandlerFactory = + (options: ResponseStreamFetchOptions) => + async () => { + const { + abortSignal, + client, + logDebugMessage, + logger, + requestBody, + responseStream, + stateHandler, + } = options; + + const fieldCandidates: string[] = []; + let fieldCandidatesCount = fieldCandidates.length; + + const textFieldCandidates: string[] = []; + + let totalDocCount = 0; + + if (!requestBody.overrides?.remainingFieldCandidates) { + logDebugMessage('Fetch index information.'); + responseStream.push( + updateLoadingStateAction({ + ccsWarning: false, + loaded: stateHandler.loaded(), + loadingState: i18n.translate( + 'xpack.aiops.logRateAnalysis.loadingState.loadingIndexInformation', + { + defaultMessage: 'Loading index information.', + } + ), + }) + ); + + try { + const indexInfo = await fetchIndexInfo( + client, + requestBody, + ['message', 'error.message'], + abortSignal + ); + + fieldCandidates.push(...indexInfo.fieldCandidates); + fieldCandidatesCount = fieldCandidates.length; + textFieldCandidates.push(...indexInfo.textFieldCandidates); + totalDocCount = indexInfo.totalDocCount; + } catch (e) { + if (!isRequestAbortedError(e)) { + logger.error(`Failed to fetch index information, got: \n${e.toString()}`); + responseStream.pushError(`Failed to fetch index information.`); + } + responseStream.end(); + return; + } + + logDebugMessage(`Total document count: ${totalDocCount}`); + + stateHandler.loaded(LOADED_FIELD_CANDIDATES, false); + + responseStream.pushPingWithTimeout(); + + responseStream.push( + updateLoadingStateAction({ + ccsWarning: false, + loaded: stateHandler.loaded(), + loadingState: i18n.translate( + 'xpack.aiops.logRateAnalysis.loadingState.identifiedFieldCandidates', + { + defaultMessage: + 'Identified {fieldCandidatesCount, plural, one {# field candidate} other {# field candidates}}.', + values: { + fieldCandidatesCount, + }, + } + ), + }) + ); + + if (fieldCandidatesCount === 0) { + responseStream.endWithUpdatedLoadingState(); + } else if (stateHandler.shouldStop()) { + logDebugMessage('shouldStop after fetching field candidates.'); + responseStream.end(); + return; + } + } + + return { fieldCandidates, textFieldCandidates }; + }; diff --git a/x-pack/plugins/aiops/server/routes/log_rate_analysis/analysis_handlers/overall_histogram_handler.ts b/x-pack/plugins/aiops/server/routes/log_rate_analysis/analysis_handlers/overall_histogram_handler.ts new file mode 100644 index 0000000000000..278cb59b40e07 --- /dev/null +++ b/x-pack/plugins/aiops/server/routes/log_rate_analysis/analysis_handlers/overall_histogram_handler.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 { KBN_FIELD_TYPES } from '@kbn/field-types'; +import { + fetchHistogramsForFields, + type NumericChartData, + type NumericHistogramField, +} from '@kbn/ml-agg-utils'; + +import type { AiopsLogRateAnalysisApiVersion as ApiVersion } from '../../../../common/api/log_rate_analysis/schema'; +import { RANDOM_SAMPLER_SEED } from '../../../../common/constants'; + +import { isRequestAbortedError } from '../../../lib/is_request_aborted_error'; + +import { getHistogramQuery } from '../queries/get_histogram_query'; + +import type { ResponseStreamFetchOptions } from '../response_stream_factory'; + +export const overallHistogramHandlerFactory = + ({ + abortSignal, + client, + requestBody, + logDebugMessage, + logger, + responseStream, + stateHandler, + }: ResponseStreamFetchOptions) => + async () => { + const histogramFields: [NumericHistogramField] = [ + { fieldName: requestBody.timeFieldName, type: KBN_FIELD_TYPES.DATE }, + ]; + + logDebugMessage('Fetch overall histogram.'); + + let overallTimeSeries: NumericChartData | undefined; + + const overallHistogramQuery = getHistogramQuery(requestBody); + + try { + overallTimeSeries = ( + (await fetchHistogramsForFields( + client, + requestBody.index, + overallHistogramQuery, + // fields + histogramFields, + // samplerShardSize + -1, + undefined, + abortSignal, + stateHandler.sampleProbability(), + RANDOM_SAMPLER_SEED + )) as [NumericChartData] + )[0]; + } catch (e) { + if (!isRequestAbortedError(e)) { + logger.error(`Failed to fetch the overall histogram data, got: \n${e.toString()}`); + responseStream.pushError(`Failed to fetch overall histogram data.`); + } + // Still continue the analysis even if loading the overall histogram fails. + } + + if (stateHandler.shouldStop()) { + logDebugMessage('shouldStop after fetching overall histogram.'); + responseStream.end(); + return; + } + + return overallTimeSeries; + }; diff --git a/x-pack/plugins/aiops/server/routes/log_rate_analysis/analysis_handlers/overrides_handler.ts b/x-pack/plugins/aiops/server/routes/log_rate_analysis/analysis_handlers/overrides_handler.ts new file mode 100644 index 0000000000000..e4a1d784bc468 --- /dev/null +++ b/x-pack/plugins/aiops/server/routes/log_rate_analysis/analysis_handlers/overrides_handler.ts @@ -0,0 +1,42 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { + resetAllAction, + resetErrorsAction, + resetGroupsAction, +} from '../../../../common/api/log_rate_analysis/actions'; +import type { AiopsLogRateAnalysisApiVersion as ApiVersion } from '../../../../common/api/log_rate_analysis/schema'; + +import type { ResponseStreamFetchOptions } from '../response_stream_factory'; + +export const overridesHandlerFactory = + ({ + requestBody, + logDebugMessage, + responseStream, + stateHandler, + }: ResponseStreamFetchOptions) => + () => { + if (!requestBody.overrides) { + logDebugMessage('Full Reset.'); + responseStream.push(resetAllAction()); + } else { + logDebugMessage('Reset Errors.'); + responseStream.push(resetErrorsAction()); + } + + if (requestBody.overrides?.regroupOnly) { + logDebugMessage('Reset Groups.'); + responseStream.push(resetGroupsAction()); + } + + if (requestBody.overrides?.loaded) { + logDebugMessage(`Set 'loaded' override to '${requestBody.overrides?.loaded}'.`); + stateHandler.loaded(requestBody.overrides?.loaded); + } + }; diff --git a/x-pack/plugins/aiops/server/routes/log_rate_analysis/analysis_handlers/significant_items_handler.ts b/x-pack/plugins/aiops/server/routes/log_rate_analysis/analysis_handlers/significant_items_handler.ts new file mode 100644 index 0000000000000..1fefba00cf023 --- /dev/null +++ b/x-pack/plugins/aiops/server/routes/log_rate_analysis/analysis_handlers/significant_items_handler.ts @@ -0,0 +1,208 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { queue } from 'async'; + +import { SIGNIFICANT_ITEM_TYPE, type SignificantItem } from '@kbn/ml-agg-utils'; +import { i18n } from '@kbn/i18n'; + +import { + addSignificantItemsAction, + updateLoadingStateAction, +} from '../../../../common/api/log_rate_analysis/actions'; + +import { isRequestAbortedError } from '../../../lib/is_request_aborted_error'; + +import { fetchSignificantCategories } from '../queries/fetch_significant_categories'; +import { fetchSignificantTermPValues } from '../queries/fetch_significant_term_p_values'; + +import type { + AiopsLogRateAnalysisSchema, + AiopsLogRateAnalysisApiVersion as ApiVersion, +} from '../../../../common/api/log_rate_analysis/schema'; + +import { + LOADED_FIELD_CANDIDATES, + MAX_CONCURRENT_QUERIES, + PROGRESS_STEP_P_VALUES, +} from '../response_stream_utils/constants'; +import type { ResponseStreamFetchOptions } from '../response_stream_factory'; + +export const significantItemsHandlerFactory = + ({ + abortSignal, + client, + logDebugMessage, + logger, + requestBody, + responseStream, + stateHandler, + version, + }: ResponseStreamFetchOptions) => + async ({ + fieldCandidates, + textFieldCandidates, + }: { + fieldCandidates: string[]; + textFieldCandidates: string[]; + }) => { + let fieldCandidatesCount = fieldCandidates.length; + + // This will store the combined count of detected significant log patterns and keywords + let fieldValuePairsCount = 0; + + const significantCategories: SignificantItem[] = []; + + if (version === '1') { + significantCategories.push( + ...((requestBody as AiopsLogRateAnalysisSchema<'1'>).overrides?.significantTerms?.filter( + (d) => d.type === SIGNIFICANT_ITEM_TYPE.LOG_PATTERN + ) ?? []) + ); + } + + if (version === '2') { + significantCategories.push( + ...((requestBody as AiopsLogRateAnalysisSchema<'2'>).overrides?.significantItems?.filter( + (d) => d.type === SIGNIFICANT_ITEM_TYPE.LOG_PATTERN + ) ?? []) + ); + } + + // Get significant categories of text fields + if (textFieldCandidates.length > 0) { + significantCategories.push( + ...(await fetchSignificantCategories( + client, + requestBody, + textFieldCandidates, + logger, + stateHandler.sampleProbability(), + responseStream.pushError, + abortSignal + )) + ); + + if (significantCategories.length > 0) { + responseStream.push(addSignificantItemsAction(significantCategories, version)); + } + } + + const significantTerms: SignificantItem[] = []; + + if (version === '1') { + significantTerms.push( + ...((requestBody as AiopsLogRateAnalysisSchema<'1'>).overrides?.significantTerms?.filter( + (d) => d.type === SIGNIFICANT_ITEM_TYPE.KEYWORD + ) ?? []) + ); + } + + if (version === '2') { + significantTerms.push( + ...((requestBody as AiopsLogRateAnalysisSchema<'2'>).overrides?.significantItems?.filter( + (d) => d.type === SIGNIFICANT_ITEM_TYPE.KEYWORD + ) ?? []) + ); + } + + const fieldsToSample = new Set(); + + let remainingFieldCandidates: string[]; + let loadingStepSizePValues = PROGRESS_STEP_P_VALUES; + + if (requestBody.overrides?.remainingFieldCandidates) { + fieldCandidates.push(...requestBody.overrides?.remainingFieldCandidates); + remainingFieldCandidates = requestBody.overrides?.remainingFieldCandidates; + fieldCandidatesCount = fieldCandidates.length; + loadingStepSizePValues = + LOADED_FIELD_CANDIDATES + + PROGRESS_STEP_P_VALUES - + (requestBody.overrides?.loaded ?? PROGRESS_STEP_P_VALUES); + } else { + remainingFieldCandidates = fieldCandidates; + } + + logDebugMessage('Fetch p-values.'); + + const pValuesQueue = queue(async function (fieldCandidate: string) { + stateHandler.loaded((1 / fieldCandidatesCount) * loadingStepSizePValues, false); + + let pValues: Awaited>; + + try { + pValues = await fetchSignificantTermPValues( + client, + requestBody, + [fieldCandidate], + logger, + stateHandler.sampleProbability(), + responseStream.pushError, + abortSignal + ); + } catch (e) { + if (!isRequestAbortedError(e)) { + logger.error(`Failed to fetch p-values for '${fieldCandidate}', got: \n${e.toString()}`); + responseStream.pushError(`Failed to fetch p-values for '${fieldCandidate}'.`); + } + return; + } + + remainingFieldCandidates = remainingFieldCandidates.filter((d) => d !== fieldCandidate); + + if (pValues.length > 0) { + pValues.forEach((d) => { + fieldsToSample.add(d.fieldName); + }); + significantTerms.push(...pValues); + + responseStream.push(addSignificantItemsAction(pValues, version)); + } + + responseStream.push( + updateLoadingStateAction({ + ccsWarning: false, + loaded: stateHandler.loaded(), + loadingState: i18n.translate( + 'xpack.aiops.logRateAnalysis.loadingState.identifiedFieldValuePairs', + { + defaultMessage: + 'Identified {fieldValuePairsCount, plural, one {# significant field/value pair} other {# significant field/value pairs}}.', + values: { + fieldValuePairsCount, + }, + } + ), + remainingFieldCandidates, + }) + ); + }, MAX_CONCURRENT_QUERIES); + + pValuesQueue.push(fieldCandidates, (err) => { + if (err) { + logger.error(`Failed to fetch p-values.', got: \n${err.toString()}`); + responseStream.pushError(`Failed to fetch p-values.`); + pValuesQueue.kill(); + responseStream.end(); + } else if (stateHandler.shouldStop()) { + logDebugMessage('shouldStop fetching p-values.'); + pValuesQueue.kill(); + responseStream.end(); + } + }); + await pValuesQueue.drain(); + + fieldValuePairsCount = significantCategories.length + significantTerms.length; + + if (fieldValuePairsCount === 0) { + logDebugMessage('Stopping analysis, did not find significant terms.'); + responseStream.endWithUpdatedLoadingState(); + return; + } + + return { fieldValuePairsCount, significantCategories, significantTerms }; + }; diff --git a/x-pack/plugins/aiops/server/routes/log_rate_analysis/define_route.ts b/x-pack/plugins/aiops/server/routes/log_rate_analysis/define_route.ts index 6f9343a50ae62..60122c7ec611f 100644 --- a/x-pack/plugins/aiops/server/routes/log_rate_analysis/define_route.ts +++ b/x-pack/plugins/aiops/server/routes/log_rate_analysis/define_route.ts @@ -18,6 +18,12 @@ import type { AiopsLicense } from '../../types'; import { routeHandlerFactory } from './route_handler_factory'; +/** + * `defineRoute` is called in the root `plugin.ts` to set up the API route + * for log pattern analysis. Its purpose is to take care of the route setup + * and versioning only. `routeHandlerFactory` is used to take care of + * the actual route logic. + */ export const defineRoute = ( router: IRouter, license: AiopsLicense, diff --git a/x-pack/plugins/aiops/server/routes/log_rate_analysis/queries/__mocks__/params_match_all.ts b/x-pack/plugins/aiops/server/routes/log_rate_analysis/queries/__mocks__/params_match_all.ts new file mode 100644 index 0000000000000..a81ba523caa43 --- /dev/null +++ b/x-pack/plugins/aiops/server/routes/log_rate_analysis/queries/__mocks__/params_match_all.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. + */ + +export const paramsMock = { + index: 'the-index', + timeFieldName: 'the-time-field-name', + start: 0, + end: 50, + baselineMin: 10, + baselineMax: 20, + deviationMin: 30, + deviationMax: 40, + includeFrozen: false, + searchQuery: '{ "match_all": {} }', +}; diff --git a/x-pack/plugins/aiops/server/routes/log_rate_analysis/queries/__mocks__/params_search_query.ts b/x-pack/plugins/aiops/server/routes/log_rate_analysis/queries/__mocks__/params_search_query.ts new file mode 100644 index 0000000000000..dd0ac80585403 --- /dev/null +++ b/x-pack/plugins/aiops/server/routes/log_rate_analysis/queries/__mocks__/params_search_query.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 type { AiopsLogRateAnalysisSchema } from '../../../../../common/api/log_rate_analysis/schema'; + +import { paramsMock } from './params_match_all'; +import { searchQueryMock } from './search_query'; + +export const paramsSearchQueryMock: AiopsLogRateAnalysisSchema = { + ...paramsMock, + searchQuery: searchQueryMock, +}; diff --git a/x-pack/plugins/aiops/server/routes/log_rate_analysis/queries/__mocks__/search_query.ts b/x-pack/plugins/aiops/server/routes/log_rate_analysis/queries/__mocks__/search_query.ts new file mode 100644 index 0000000000000..58be3bf372711 --- /dev/null +++ b/x-pack/plugins/aiops/server/routes/log_rate_analysis/queries/__mocks__/search_query.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. + */ + +// This is the format that gets passed on from the Kibana search bar. +export const searchQueryMock = JSON.stringify({ + bool: { + filter: [], + minimum_should_match: 1, + must_not: [], + should: [{ term: { 'the-term': { value: 'the-value' } } }], + }, +}); diff --git a/x-pack/plugins/aiops/server/routes/log_rate_analysis/queries/fetch_categories.test.ts b/x-pack/plugins/aiops/server/routes/log_rate_analysis/queries/fetch_categories.test.ts new file mode 100644 index 0000000000000..d38dd57c0afd2 --- /dev/null +++ b/x-pack/plugins/aiops/server/routes/log_rate_analysis/queries/fetch_categories.test.ts @@ -0,0 +1,100 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { createRandomSamplerWrapper } from '@kbn/ml-random-sampler-utils'; + +import { paramsMock } from './__mocks__/params_match_all'; +import { getBaselineOrDeviationFilter, getCategoryRequest } from './fetch_categories'; + +describe('getBaselineOrDeviationFilter', () => { + it('returns a filter that matches both baseline and deviation time range', () => { + const baselineOrDeviationFilter = getBaselineOrDeviationFilter(paramsMock); + + expect(baselineOrDeviationFilter).toEqual({ + bool: { + should: [ + { + range: { + 'the-time-field-name': { gte: 10, lte: 20, format: 'epoch_millis' }, + }, + }, + { + range: { + 'the-time-field-name': { gte: 30, lte: 40, format: 'epoch_millis' }, + }, + }, + ], + }, + }); + }); +}); + +describe('getCategoryRequest', () => { + it('returns the category request', () => { + const randomSamplerWrapper = createRandomSamplerWrapper({ + probability: 0.1, + seed: 1234, + }); + + const query = getCategoryRequest(paramsMock, 'the-field-name', randomSamplerWrapper); + + // Because the time range filter is covered by the should clauses that cover both + // baseline (10,20) and deviation (30,40), we expect that there is no other + // time range filter whatsoever, for example for start/end (0,50). + expect(query).toEqual({ + index: 'the-index', + size: 0, + body: { + query: { + bool: { + filter: [ + { + bool: { + should: [ + { + range: { + 'the-time-field-name': { + gte: 10, + lte: 20, + format: 'epoch_millis', + }, + }, + }, + { + range: { + 'the-time-field-name': { + gte: 30, + lte: 40, + format: 'epoch_millis', + }, + }, + }, + ], + }, + }, + ], + }, + }, + aggs: { + sample: { + random_sampler: { probability: 0.1, seed: 1234 }, + aggs: { + categories: { + categorize_text: { field: 'the-field-name', size: 1000 }, + aggs: { + hit: { + top_hits: { size: 1, sort: ['the-time-field-name'], _source: 'the-field-name' }, + }, + }, + }, + }, + }, + }, + }, + }); + }); +}); diff --git a/x-pack/plugins/aiops/server/routes/log_rate_analysis/queries/fetch_categories.ts b/x-pack/plugins/aiops/server/routes/log_rate_analysis/queries/fetch_categories.ts index e70255ababffd..703242b7e9a6a 100644 --- a/x-pack/plugins/aiops/server/routes/log_rate_analysis/queries/fetch_categories.ts +++ b/x-pack/plugins/aiops/server/routes/log_rate_analysis/queries/fetch_categories.ts @@ -28,30 +28,67 @@ import { isRequestAbortedError } from '../../../lib/is_request_aborted_error'; import { getQueryWithParams } from './get_query_with_params'; +// Filter that includes docs from both the baseline and deviation time range. +export const getBaselineOrDeviationFilter = ( + params: AiopsLogRateAnalysisSchema +): estypes.QueryDslQueryContainer => { + return { + bool: { + should: [ + { + range: { + [params.timeFieldName]: { + gte: params.baselineMin, + lte: params.baselineMax, + format: 'epoch_millis', + }, + }, + }, + { + range: { + [params.timeFieldName]: { + gte: params.deviationMin, + lte: params.deviationMax, + format: 'epoch_millis', + }, + }, + }, + ], + }, + }; +}; + export const getCategoryRequest = ( params: AiopsLogRateAnalysisSchema, fieldName: string, - from: number | undefined, - to: number | undefined, - filter: estypes.QueryDslQueryContainer, { wrap }: RandomSamplerWrapper ): estypes.SearchRequest => { const { index, timeFieldName } = params; + const query = getQueryWithParams({ params, - termFilters: undefined, - filter, + // We're skipping the overall range query here since this + // is covered by the filter which will match docs in both baseline + // and deviation time range via `getBaselineOrDeviationFilter`. + skipRangeQuery: true, + filter: getBaselineOrDeviationFilter(params), }); + const { params: request } = createCategoryRequest( index, fieldName, timeFieldName, - from, - to, + undefined, + undefined, query, wrap ); + // In this case we're only interested in the aggregation which + // `createCategoryRequest` returns, so we're re-applying the original + // query we create via `getQueryWithParams` here. + request.body.query = query; + return request; }; @@ -64,9 +101,6 @@ export const fetchCategories = async ( esClient: ElasticsearchClient, params: AiopsLogRateAnalysisSchema, fieldNames: string[], - from: number | undefined, - to: number | undefined, - filter: estypes.QueryDslQueryContainer, logger: Logger, // The default value of 1 means no sampling will be used sampleProbability: number = 1, @@ -82,7 +116,7 @@ export const fetchCategories = async ( const settledPromises = await Promise.allSettled( fieldNames.map((fieldName) => { - const request = getCategoryRequest(params, fieldName, from, to, filter, randomSamplerWrapper); + const request = getCategoryRequest(params, fieldName, randomSamplerWrapper); return esClient.search(request, { signal: abortSignal, maxRetries: 0, diff --git a/x-pack/plugins/aiops/server/routes/log_rate_analysis/queries/fetch_category_counts.test.ts b/x-pack/plugins/aiops/server/routes/log_rate_analysis/queries/fetch_category_counts.test.ts new file mode 100644 index 0000000000000..b3fa6ff5f31a8 --- /dev/null +++ b/x-pack/plugins/aiops/server/routes/log_rate_analysis/queries/fetch_category_counts.test.ts @@ -0,0 +1,139 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { paramsMock } from './__mocks__/params_match_all'; + +import { getCategoryCountRequest, getCategoryCountMSearchRequest } from './fetch_category_counts'; + +describe('getCategoryCountRequest', () => { + it('returns the category count request', () => { + const category = { + key: 'runTask ended no files to process', + count: 667, + examples: ['[runTask()] ended: no files to process'], + }; + + const query = getCategoryCountRequest( + paramsMock, + 'the-field-name', + category, + paramsMock.baselineMin, + paramsMock.baselineMax + ); + + expect(query).toEqual({ + index: 'the-index', + body: { + query: { + bool: { + filter: [ + { range: { 'the-time-field-name': { gte: 10, lte: 20, format: 'epoch_millis' } } }, + { + bool: { + should: [ + { + match: { + 'the-field-name': { + auto_generate_synonyms_phrase_query: false, + fuzziness: 0, + operator: 'and', + query: 'runTask ended no files to process', + }, + }, + }, + ], + }, + }, + ], + }, + }, + size: 0, + track_total_hits: true, + }, + }); + }); +}); + +describe('getCategoryCountMSearchRequest', () => { + it('returns the request body for the msearch request', () => { + const categories = [ + { + key: 'SLO summary transforms installed and started', + count: 500, + examples: ['SLO summary transforms installed and started'], + }, + { key: 'Trusted Apps', count: 500, examples: ['Trusted Apps: '] }, + ]; + + const query = getCategoryCountMSearchRequest( + paramsMock, + 'the-field-name', + categories, + paramsMock.baselineMin, + paramsMock.baselineMax + ); + + expect(query).toEqual([ + { index: 'the-index' }, + { + query: { + bool: { + filter: [ + { range: { 'the-time-field-name': { gte: 10, lte: 20, format: 'epoch_millis' } } }, + { + bool: { + should: [ + { + match: { + 'the-field-name': { + auto_generate_synonyms_phrase_query: false, + fuzziness: 0, + operator: 'and', + query: 'SLO summary transforms installed and started', + }, + }, + }, + ], + }, + }, + ], + }, + }, + size: 0, + track_total_hits: true, + }, + { index: 'the-index' }, + { + query: { + bool: { + filter: [ + { range: { 'the-time-field-name': { gte: 10, lte: 20, format: 'epoch_millis' } } }, + { + bool: { + should: [ + { + match: { + 'the-field-name': { + auto_generate_synonyms_phrase_query: false, + fuzziness: 0, + operator: 'and', + query: 'Trusted Apps', + }, + }, + }, + ], + }, + }, + ], + }, + }, + size: 0, + track_total_hits: true, + }, + ]); + }); +}); diff --git a/x-pack/plugins/aiops/server/routes/log_rate_analysis/queries/fetch_category_counts.ts b/x-pack/plugins/aiops/server/routes/log_rate_analysis/queries/fetch_category_counts.ts index 608734ae0e19a..555d49b46dc19 100644 --- a/x-pack/plugins/aiops/server/routes/log_rate_analysis/queries/fetch_category_counts.ts +++ b/x-pack/plugins/aiops/server/routes/log_rate_analysis/queries/fetch_category_counts.ts @@ -33,24 +33,18 @@ export const getCategoryCountRequest = ( ): estypes.SearchRequest => { const { index } = params; - const query = getQueryWithParams({ - params, - }); - const categoryQuery = getCategoryQuery(fieldName, [category]); - if (Array.isArray(query.bool?.filter)) { - query.bool?.filter?.push(categoryQuery); - query.bool?.filter?.push({ - range: { - [params.timeFieldName]: { - gte: from, - lte: to, - format: 'epoch_millis', - }, - }, - }); - } + const query = getQueryWithParams({ + // This will override the original start/end params if + // the optional from/to args are provided. + params: { + ...params, + ...(from ? { start: from } : {}), + ...(to ? { end: to } : {}), + }, + filter: categoryQuery, + }); return { index, @@ -62,6 +56,19 @@ export const getCategoryCountRequest = ( }; }; +export const getCategoryCountMSearchRequest = ( + params: AiopsLogRateAnalysisSchema, + fieldName: string, + categories: FetchCategoriesResponse['categories'], + from: number | undefined, + to: number | undefined +): estypes.MsearchRequestItem[] => + categories.flatMap((category) => [ + { index: params.index }, + getCategoryCountRequest(params, fieldName, category, from, to) + .body as estypes.MsearchMultisearchBody, + ]); + export const fetchCategoryCounts = async ( esClient: ElasticsearchClient, params: AiopsLogRateAnalysisSchema, @@ -75,11 +82,13 @@ export const fetchCategoryCounts = async ( ): Promise => { const updatedCategories = cloneDeep(categories); - const searches = categories.categories.flatMap((category) => [ - { index: params.index }, - getCategoryCountRequest(params, fieldName, category, from, to) - .body as estypes.MsearchMultisearchBody, - ]); + const searches = getCategoryCountMSearchRequest( + params, + fieldName, + categories.categories, + from, + to + ); let mSearchresponse; diff --git a/x-pack/plugins/aiops/server/routes/log_rate_analysis/queries/fetch_index_info.test.ts b/x-pack/plugins/aiops/server/routes/log_rate_analysis/queries/fetch_index_info.test.ts index db14c30caebdc..0344005c869f8 100644 --- a/x-pack/plugins/aiops/server/routes/log_rate_analysis/queries/fetch_index_info.test.ts +++ b/x-pack/plugins/aiops/server/routes/log_rate_analysis/queries/fetch_index_info.test.ts @@ -9,27 +9,14 @@ import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import type { ElasticsearchClient } from '@kbn/core/server'; -import type { AiopsLogRateAnalysisSchema } from '../../../../common/api/log_rate_analysis/schema'; +import { paramsSearchQueryMock } from './__mocks__/params_search_query'; import { fetchIndexInfo, getRandomDocsRequest } from './fetch_index_info'; -const params: AiopsLogRateAnalysisSchema = { - index: 'the-index', - timeFieldName: 'the-time-field-name', - start: 1577836800000, - end: 1609459200000, - baselineMin: 10, - baselineMax: 20, - deviationMin: 30, - deviationMax: 40, - includeFrozen: false, - searchQuery: '{"bool":{"filter":[],"must":[{"match_all":{}}],"must_not":[]}}', -}; - describe('fetch_index_info', () => { describe('getRandomDocsRequest', () => { it('returns the most basic request body for a sample of random documents', () => { - const req = getRandomDocsRequest(params); + const req = getRandomDocsRequest(paramsSearchQueryMock); expect(req).toEqual({ body: { @@ -40,13 +27,20 @@ describe('fetch_index_info', () => { query: { bool: { filter: [ - { bool: { filter: [], must: [{ match_all: {} }], must_not: [] } }, + { + bool: { + filter: [], + minimum_should_match: 1, + must_not: [], + should: [{ term: { 'the-term': { value: 'the-value' } } }], + }, + }, { range: { 'the-time-field-name': { format: 'epoch_millis', - gte: 1577836800000, - lte: 1609459200000, + gte: 0, + lte: 50, }, }, }, @@ -59,7 +53,7 @@ describe('fetch_index_info', () => { size: 1000, track_total_hits: true, }, - index: params.index, + index: paramsSearchQueryMock.index, ignore_throttled: undefined, ignore_unavailable: true, }); @@ -105,7 +99,10 @@ describe('fetch_index_info', () => { search: esClientSearchMock, } as unknown as ElasticsearchClient; - const { totalDocCount, fieldCandidates } = await fetchIndexInfo(esClientMock, params); + const { totalDocCount, fieldCandidates } = await fetchIndexInfo( + esClientMock, + paramsSearchQueryMock + ); expect(fieldCandidates).toEqual(['myIpFieldName', 'myKeywordFieldName']); expect(totalDocCount).toEqual(5000000); diff --git a/x-pack/plugins/aiops/server/routes/log_rate_analysis/queries/fetch_significant_categories.ts b/x-pack/plugins/aiops/server/routes/log_rate_analysis/queries/fetch_significant_categories.ts index 49617a1661ba6..2284622dc808c 100644 --- a/x-pack/plugins/aiops/server/routes/log_rate_analysis/queries/fetch_significant_categories.ts +++ b/x-pack/plugins/aiops/server/routes/log_rate_analysis/queries/fetch_significant_categories.ts @@ -42,39 +42,10 @@ export const fetchSignificantCategories = async ( emitError: (m: string) => void, abortSignal?: AbortSignal ) => { - // Filter that includes docs from both the baseline and deviation time range. - const baselineOrDeviationFilter = { - bool: { - should: [ - { - range: { - [params.timeFieldName]: { - gte: params.baselineMin, - lte: params.baselineMax, - format: 'epoch_millis', - }, - }, - }, - { - range: { - [params.timeFieldName]: { - gte: params.deviationMin, - lte: params.deviationMax, - format: 'epoch_millis', - }, - }, - }, - ], - }, - }; - const categoriesOverall = await fetchCategories( esClient, params, fieldNames, - undefined, - undefined, - baselineOrDeviationFilter, logger, sampleProbability, emitError, diff --git a/x-pack/plugins/aiops/server/routes/log_rate_analysis/queries/get_filters.test.ts b/x-pack/plugins/aiops/server/routes/log_rate_analysis/queries/get_filters.test.ts deleted file mode 100644 index c34d81fa91bdf..0000000000000 --- a/x-pack/plugins/aiops/server/routes/log_rate_analysis/queries/get_filters.test.ts +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { getFilters } from './get_filters'; - -describe('getFilters', () => { - it('returns an empty array with no timeFieldName and searchQuery supplied', () => { - const filters = getFilters({ - index: 'the-index', - timeFieldName: '', - searchQuery: '{"bool":{"filter":[],"must":[{"match_all":{}}],"must_not":[]}}', - start: 1577836800000, - end: 1609459200000, - baselineMin: 10, - baselineMax: 20, - deviationMin: 30, - deviationMax: 40, - }); - expect(filters).toEqual([]); - }); - - it('returns a range filter when timeFieldName is supplied', () => { - const filters = getFilters({ - index: 'the-index', - timeFieldName: 'the-time-field-name', - searchQuery: '{"bool":{"filter":[],"must":[{"match_all":{}}],"must_not":[]}}', - start: 1577836800000, - end: 1609459200000, - baselineMin: 10, - baselineMax: 20, - deviationMin: 30, - deviationMax: 40, - }); - expect(filters).toEqual([ - { - range: { - 'the-time-field-name': { - format: 'epoch_millis', - gte: 1577836800000, - lte: 1609459200000, - }, - }, - }, - ]); - }); -}); diff --git a/x-pack/plugins/aiops/server/routes/log_rate_analysis/queries/get_filters.ts b/x-pack/plugins/aiops/server/routes/log_rate_analysis/queries/get_filters.ts deleted file mode 100644 index e910d2e997441..0000000000000 --- a/x-pack/plugins/aiops/server/routes/log_rate_analysis/queries/get_filters.ts +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; - -import type { ESFilter } from '@kbn/es-types'; - -import type { AiopsLogRateAnalysisSchema } from '../../../../common/api/log_rate_analysis/schema'; - -export function rangeQuery( - start?: number, - end?: number, - field = '@timestamp' -): estypes.QueryDslQueryContainer[] { - return [ - { - range: { - [field]: { - gte: start, - lte: end, - format: 'epoch_millis', - }, - }, - }, - ]; -} - -export function getFilters({ start, end, timeFieldName }: AiopsLogRateAnalysisSchema): ESFilter[] { - const filters: ESFilter[] = []; - - if (timeFieldName !== '') { - filters.push(...rangeQuery(start, end, timeFieldName)); - } - - return filters; -} diff --git a/x-pack/plugins/aiops/server/routes/log_rate_analysis/queries/get_histogram_query.test.ts b/x-pack/plugins/aiops/server/routes/log_rate_analysis/queries/get_histogram_query.test.ts index 95113d39f41c8..39af620dd266a 100644 --- a/x-pack/plugins/aiops/server/routes/log_rate_analysis/queries/get_histogram_query.test.ts +++ b/x-pack/plugins/aiops/server/routes/log_rate_analysis/queries/get_histogram_query.test.ts @@ -5,34 +5,30 @@ * 2.0. */ -import { getHistogramQuery } from './get_histogram_query'; +import { paramsSearchQueryMock } from './__mocks__/params_search_query'; -const paramsMock = { - index: 'the-index', - timeFieldName: 'the-time-field-name', - start: 1577836800000, - end: 1609459200000, - baselineMin: 10, - baselineMax: 20, - deviationMin: 30, - deviationMax: 40, - includeFrozen: false, - searchQuery: '{"bool":{"filter":[],"must":[{"match_all":{}}],"must_not":[]}}', -}; +import { getHistogramQuery } from './get_histogram_query'; describe('getHistogramQuery', () => { it('returns histogram query without additional filters', () => { - const query = getHistogramQuery(paramsMock); + const query = getHistogramQuery(paramsSearchQueryMock); expect(query).toEqual({ bool: { filter: [ - { bool: { filter: [], must: [{ match_all: {} }], must_not: [] } }, + { + bool: { + filter: [], + minimum_should_match: 1, + must_not: [], + should: [{ term: { 'the-term': { value: 'the-value' } } }], + }, + }, { range: { 'the-time-field-name': { format: 'epoch_millis', - gte: 1577836800000, - lte: 1609459200000, + gte: 0, + lte: 50, }, }, }, @@ -42,7 +38,7 @@ describe('getHistogramQuery', () => { }); it('returns histogram query with additional filters', () => { - const query = getHistogramQuery(paramsMock, [ + const query = getHistogramQuery(paramsSearchQueryMock, [ { term: { ['the-filter-fieldName']: 'the-filter-fieldValue' }, }, @@ -50,7 +46,14 @@ describe('getHistogramQuery', () => { expect(query).toEqual({ bool: { filter: [ - { bool: { filter: [], must: [{ match_all: {} }], must_not: [] } }, + { + bool: { + filter: [], + minimum_should_match: 1, + must_not: [], + should: [{ term: { 'the-term': { value: 'the-value' } } }], + }, + }, { term: { 'the-filter-fieldName': 'the-filter-fieldValue', @@ -60,8 +63,8 @@ describe('getHistogramQuery', () => { range: { 'the-time-field-name': { format: 'epoch_millis', - gte: 1577836800000, - lte: 1609459200000, + gte: 0, + lte: 50, }, }, }, diff --git a/x-pack/plugins/aiops/server/routes/log_rate_analysis/queries/get_query_with_params.test.ts b/x-pack/plugins/aiops/server/routes/log_rate_analysis/queries/get_query_with_params.test.ts index aa600065fd223..cd43e031e916a 100644 --- a/x-pack/plugins/aiops/server/routes/log_rate_analysis/queries/get_query_with_params.test.ts +++ b/x-pack/plugins/aiops/server/routes/log_rate_analysis/queries/get_query_with_params.test.ts @@ -5,34 +5,33 @@ * 2.0. */ +import { paramsMock } from './__mocks__/params_match_all'; +import { paramsSearchQueryMock } from './__mocks__/params_search_query'; + import { getQueryWithParams } from './get_query_with_params'; describe('getQueryWithParams', () => { it('returns the most basic query filtering', () => { const query = getQueryWithParams({ - params: { - index: 'the-index', - timeFieldName: 'the-time-field-name', - start: 1577836800000, - end: 1609459200000, - baselineMin: 10, - baselineMax: 20, - deviationMin: 30, - deviationMax: 40, - includeFrozen: false, - searchQuery: '{"bool":{"filter":[],"must":[{"match_all":{}}],"must_not":[]}}', - }, + params: paramsSearchQueryMock, }); expect(query).toEqual({ bool: { filter: [ - { bool: { filter: [], must: [{ match_all: {} }], must_not: [] } }, + { + bool: { + filter: [], + minimum_should_match: 1, + must_not: [], + should: [{ term: { 'the-term': { value: 'the-value' } } }], + }, + }, { range: { 'the-time-field-name': { format: 'epoch_millis', - gte: 1577836800000, - lte: 1609459200000, + gte: 0, + lte: 50, }, }, }, @@ -43,18 +42,7 @@ describe('getQueryWithParams', () => { it('returns a query considering a custom field/value pair', () => { const query = getQueryWithParams({ - params: { - index: 'the-index', - timeFieldName: 'the-time-field-name', - start: 1577836800000, - end: 1609459200000, - baselineMin: 10, - baselineMax: 20, - deviationMin: 30, - deviationMax: 40, - includeFrozen: false, - searchQuery: '{"bool":{"filter":[],"must":[{"match_all":{}}],"must_not":[]}}', - }, + params: paramsSearchQueryMock, termFilters: [ { fieldName: 'actualFieldName', @@ -65,13 +53,20 @@ describe('getQueryWithParams', () => { expect(query).toEqual({ bool: { filter: [ - { bool: { filter: [], must: [{ match_all: {} }], must_not: [] } }, + { + bool: { + filter: [], + minimum_should_match: 1, + must_not: [], + should: [{ term: { 'the-term': { value: 'the-value' } } }], + }, + }, { range: { 'the-time-field-name': { format: 'epoch_millis', - gte: 1577836800000, - lte: 1609459200000, + gte: 0, + lte: 50, }, }, }, @@ -84,4 +79,25 @@ describe('getQueryWithParams', () => { }, }); }); + + it("should not add `searchQuery` if it's just a match_all query", () => { + const query = getQueryWithParams({ + params: paramsMock, + }); + expect(query).toEqual({ + bool: { + filter: [ + { + range: { + 'the-time-field-name': { + format: 'epoch_millis', + gte: 0, + lte: 50, + }, + }, + }, + ], + }, + }); + }); }); diff --git a/x-pack/plugins/aiops/server/routes/log_rate_analysis/queries/get_query_with_params.ts b/x-pack/plugins/aiops/server/routes/log_rate_analysis/queries/get_query_with_params.ts index b7e2e2619316a..80d67fe73fa81 100644 --- a/x-pack/plugins/aiops/server/routes/log_rate_analysis/queries/get_query_with_params.ts +++ b/x-pack/plugins/aiops/server/routes/log_rate_analysis/queries/get_query_with_params.ts @@ -11,7 +11,7 @@ import type { FieldValuePair } from '@kbn/ml-agg-utils'; import type { AiopsLogRateAnalysisSchema } from '../../../../common/api/log_rate_analysis/schema'; -import { getFilters } from './get_filters'; +import { getRangeQuery } from './get_range_query'; export const getTermsQuery = ({ fieldName, fieldValue }: FieldValuePair) => { return { term: { [fieldName]: fieldValue } }; @@ -21,21 +21,30 @@ interface QueryParams { params: AiopsLogRateAnalysisSchema<'2'>; termFilters?: FieldValuePair[]; filter?: estypes.QueryDslQueryContainer; + skipRangeQuery?: boolean; } export const getQueryWithParams = ({ params, termFilters, filter, + skipRangeQuery = false, }: QueryParams): estypes.QueryDslQueryContainer => { const searchQuery = JSON.parse(params.searchQuery) as estypes.QueryDslQueryContainer; return { bool: { filter: [ - searchQuery, - ...getFilters(params), + // Add `searchQuery` if it's not a `match_all` query + ...(searchQuery.match_all === undefined ? [searchQuery] : []), + + // Add a range query based on `start/end` for the `timeFieldName`, check for skip flag. + ...(!skipRangeQuery ? [getRangeQuery(params.start, params.end, params.timeFieldName)] : []), + + // Add optional term filters ...(Array.isArray(termFilters) ? termFilters.map(getTermsQuery) : []), + + // Add other optional filters ...(filter ? [filter] : []), - ] as estypes.QueryDslQueryContainer[], + ], }, }; }; diff --git a/x-pack/plugins/aiops/server/routes/log_rate_analysis/queries/get_range_query.test.ts b/x-pack/plugins/aiops/server/routes/log_rate_analysis/queries/get_range_query.test.ts new file mode 100644 index 0000000000000..8d232df5d2c23 --- /dev/null +++ b/x-pack/plugins/aiops/server/routes/log_rate_analysis/queries/get_range_query.test.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 { getRangeQuery } from './get_range_query'; + +describe('getRangeQuery', () => { + it('returns a range filter with default time field', () => { + const query = getRangeQuery(0, 50); + expect(query).toEqual({ + range: { + '@timestamp': { + gte: 0, + lte: 50, + format: 'epoch_millis', + }, + }, + }); + }); + + it('returns a range filter with a custom time field', () => { + const query = getRangeQuery(0, 50, 'the-time-field'); + expect(query).toEqual({ + range: { + 'the-time-field': { + gte: 0, + lte: 50, + format: 'epoch_millis', + }, + }, + }); + }); +}); diff --git a/x-pack/plugins/aiops/server/routes/log_rate_analysis/queries/get_range_query.ts b/x-pack/plugins/aiops/server/routes/log_rate_analysis/queries/get_range_query.ts new file mode 100644 index 0000000000000..ca9ae7a299ee7 --- /dev/null +++ b/x-pack/plugins/aiops/server/routes/log_rate_analysis/queries/get_range_query.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 * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; + +export function getRangeQuery( + start?: number, + end?: number, + field = '@timestamp' +): estypes.QueryDslQueryContainer { + return { + range: { + [field]: { + gte: start, + lte: end, + format: 'epoch_millis', + }, + }, + }; +} diff --git a/x-pack/plugins/aiops/server/routes/log_rate_analysis/queries/get_request_base.test.ts b/x-pack/plugins/aiops/server/routes/log_rate_analysis/queries/get_request_base.test.ts index ee21cb985f5d6..33797e219fd37 100644 --- a/x-pack/plugins/aiops/server/routes/log_rate_analysis/queries/get_request_base.test.ts +++ b/x-pack/plugins/aiops/server/routes/log_rate_analysis/queries/get_request_base.test.ts @@ -5,36 +5,20 @@ * 2.0. */ +import { paramsMock } from './__mocks__/params_match_all'; + import { getRequestBase } from './get_request_base'; describe('getRequestBase', () => { it('defaults to not setting `ignore_throttled`', () => { - const requestBase = getRequestBase({ - index: 'the-index', - timeFieldName: 'the-time-field-name', - searchQuery: '{"bool":{"filter":[],"must":[{"match_all":{}}],"must_not":[]}}', - start: 1577836800000, - end: 1609459200000, - baselineMin: 10, - baselineMax: 20, - deviationMin: 30, - deviationMax: 40, - }); + const requestBase = getRequestBase(paramsMock); expect(requestBase.ignore_throttled).toEqual(undefined); }); it('adds `ignore_throttled=false` when `includeFrozen=true`', () => { const requestBase = getRequestBase({ - index: 'the-index', - timeFieldName: 'the-time-field-name', + ...paramsMock, includeFrozen: true, - searchQuery: '{"bool":{"filter":[],"must":[{"match_all":{}}],"must_not":[]}}', - start: 1577836800000, - end: 1609459200000, - baselineMin: 10, - baselineMax: 20, - deviationMin: 30, - deviationMax: 40, }); expect(requestBase.ignore_throttled).toEqual(false); }); diff --git a/x-pack/plugins/aiops/server/routes/log_rate_analysis/response_stream_factory.ts b/x-pack/plugins/aiops/server/routes/log_rate_analysis/response_stream_factory.ts new file mode 100644 index 0000000000000..f54c2e93dd29e --- /dev/null +++ b/x-pack/plugins/aiops/server/routes/log_rate_analysis/response_stream_factory.ts @@ -0,0 +1,137 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { streamFactory, type StreamFactoryReturnType } from '@kbn/ml-response-stream/server'; +import type { ElasticsearchClient } from '@kbn/core/server'; +import type { Headers, KibanaRequestEvents } from '@kbn/core-http-server'; +import type { Logger } from '@kbn/logging'; + +import { type AiopsLogRateAnalysisApiAction } from '../../../common/api/log_rate_analysis/actions'; + +import type { + AiopsLogRateAnalysisSchema, + AiopsLogRateAnalysisApiVersion as ApiVersion, +} from '../../../common/api/log_rate_analysis/schema'; + +import { indexInfoHandlerFactory } from './analysis_handlers/index_info_handler'; +import { groupingHandlerFactory } from './analysis_handlers/grouping_handler'; +import { histogramHandlerFactory } from './analysis_handlers/histogram_handler'; +import { overridesHandlerFactory } from './analysis_handlers/overrides_handler'; +import { significantItemsHandlerFactory } from './analysis_handlers/significant_items_handler'; +import { overallHistogramHandlerFactory } from './analysis_handlers/overall_histogram_handler'; +import { + logDebugMessageFactory, + type LogDebugMessage, +} from './response_stream_utils/log_debug_message'; +import { stateHandlerFactory, type StateHandler } from './response_stream_utils/state_handler'; +import { streamEndFactory } from './response_stream_utils/stream_end'; +import { streamEndWithUpdatedLoadingStateFactory } from './response_stream_utils/stream_end_with_updated_loading_state'; +import { streamPushErrorFactory } from './response_stream_utils/stream_push_error'; +import { streamPushPingWithTimeoutFactory } from './response_stream_utils/stream_push_ping_with_timeout'; + +/** + * The options to be passed in to `responseStreamFactory`. + */ +export interface ResponseStreamOptions { + version: T; + client: ElasticsearchClient; + requestBody: AiopsLogRateAnalysisSchema; + events: KibanaRequestEvents; + headers: Headers; + logger: Logger; +} + +/** + * The full options object that will be passed on to analysis handlers + * so they're able to access all necessary runtime dependencies. + */ +export interface ResponseStreamFetchOptions extends ResponseStreamOptions { + abortSignal: AbortSignal; + logDebugMessage: LogDebugMessage; + responseStream: { + end: () => void; + endWithUpdatedLoadingState: () => void; + push: StreamFactoryReturnType>['push']; + pushPingWithTimeout: () => void; + pushError: (msg: string) => void; + }; + stateHandler: StateHandler; +} + +/** + * `responseStreamFactory` sets up the response stream, the stream's state (for example + * if it's running, how far the stream progressed etc.), some custom actions for the stream + * as well as analysis handlers that fetch data from ES and pass it on to the stream. + * This factory should avoid to include any logic, its purpose is to take care of setting up + * and passing around dependencies for the various other parts involved + * running the analysis. + */ +export const responseStreamFactory = (options: ResponseStreamOptions) => { + const { events, headers, logger, requestBody } = options; + + const logDebugMessage = logDebugMessageFactory(logger); + const state = stateHandlerFactory({ + groupingEnabled: !!requestBody.grouping, + sampleProbability: requestBody.sampleProbability ?? 1, + }); + const controller = new AbortController(); + const abortSignal = controller.signal; + + events.aborted$.subscribe(() => { + logDebugMessage('aborted$ subscription trigger.'); + state.shouldStop(true); + controller.abort(); + }); + events.completed$.subscribe(() => { + logDebugMessage('completed$ subscription trigger.'); + state.shouldStop(true); + controller.abort(); + }); + + const { + end: streamEnd, + push, + responseWithHeaders, + } = streamFactory>( + headers, + logger, + requestBody.compressResponse, + requestBody.flushFix + ); + + const pushPingWithTimeout = streamPushPingWithTimeoutFactory(state, push, logDebugMessage); + const end = streamEndFactory(state, streamEnd, logDebugMessage); + const endWithUpdatedLoadingState = streamEndWithUpdatedLoadingStateFactory(end, push); + const pushError = streamPushErrorFactory(push, logDebugMessage); + + const streamFetchOptions: ResponseStreamFetchOptions = { + ...options, + abortSignal, + logDebugMessage, + responseStream: { + end, + endWithUpdatedLoadingState, + push, + pushError, + pushPingWithTimeout, + }, + stateHandler: state, + }; + + return { + ...streamFetchOptions, + analysis: { + indexInfoHandler: indexInfoHandlerFactory(streamFetchOptions), + groupingHandler: groupingHandlerFactory(streamFetchOptions), + histogramHandler: histogramHandlerFactory(streamFetchOptions), + overallHistogramHandler: overallHistogramHandlerFactory(streamFetchOptions), + overridesHandler: overridesHandlerFactory(streamFetchOptions), + significantItemsHandler: significantItemsHandlerFactory(streamFetchOptions), + }, + responseWithHeaders, + }; +}; diff --git a/x-pack/plugins/aiops/server/routes/log_rate_analysis/response_stream_utils/constants.ts b/x-pack/plugins/aiops/server/routes/log_rate_analysis/response_stream_utils/constants.ts new file mode 100644 index 0000000000000..3069015070239 --- /dev/null +++ b/x-pack/plugins/aiops/server/routes/log_rate_analysis/response_stream_utils/constants.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. + */ + +// Overall progress is a float from 0 to 1. +export const LOADED_FIELD_CANDIDATES = 0.2; +export const PROGRESS_STEP_P_VALUES = 0.5; +export const PROGRESS_STEP_GROUPING = 0.1; +export const PROGRESS_STEP_HISTOGRAMS = 0.1; +export const PROGRESS_STEP_HISTOGRAMS_GROUPS = 0.1; + +// Don't use more than 10 here otherwise Kibana will emit an error +// regarding a limit of abort signal listeners of more than 10. +export const MAX_CONCURRENT_QUERIES = 10; diff --git a/x-pack/plugins/aiops/server/routes/log_rate_analysis/response_stream_utils/log_debug_message.ts b/x-pack/plugins/aiops/server/routes/log_rate_analysis/response_stream_utils/log_debug_message.ts new file mode 100644 index 0000000000000..72a61ba93ca7d --- /dev/null +++ b/x-pack/plugins/aiops/server/routes/log_rate_analysis/response_stream_utils/log_debug_message.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 type { Logger } from '@kbn/logging'; + +export type LogDebugMessage = (msg: string) => void; + +export const logDebugMessageFactory = (logger: Logger): LogDebugMessage => { + let logMessageCounter = 0; + + return (msg: string) => { + logMessageCounter++; + logger.debug(`Log Rate Analysis #${logMessageCounter}: ${msg}`); + }; +}; diff --git a/x-pack/plugins/aiops/server/routes/log_rate_analysis/response_stream_utils/state_handler.ts b/x-pack/plugins/aiops/server/routes/log_rate_analysis/response_stream_utils/state_handler.ts new file mode 100644 index 0000000000000..98763170083f6 --- /dev/null +++ b/x-pack/plugins/aiops/server/routes/log_rate_analysis/response_stream_utils/state_handler.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. + */ + +export interface StreamState { + isRunning: boolean; + groupingEnabled: boolean; + loaded: number; + sampleProbability: number; + shouldStop: boolean; +} + +const getDefaultStreamState = (overrides: Partial): StreamState => ({ + isRunning: !!overrides.isRunning, + groupingEnabled: !!overrides.groupingEnabled, + loaded: overrides.loaded ?? 0, + sampleProbability: overrides.sampleProbability ?? 1, + shouldStop: !!overrides.shouldStop, +}); + +/** + * `stateHandlerFactory` takes care of handling the inner state of the stream, + * for example how much of the stream has been completed, if the stream is running etc. + * It exposes the state as getter/setter functions, for example `loaded()` will + * retrieve the current loading state, `loaded(0.5)` will update it. + */ +export const stateHandlerFactory = (overrides: Partial) => { + const state = getDefaultStreamState(overrides); + + function groupingEnabled(d?: boolean) { + if (typeof d === 'boolean') { + state.groupingEnabled = d; + } else { + return state.groupingEnabled; + } + } + + function loaded(): number; + function loaded(d: number, replace?: boolean): undefined; + function loaded(d?: number, replace = true) { + if (typeof d === 'number') { + if (replace) { + state.loaded = d; + } else { + state.loaded += d; + } + } else { + return state.loaded; + } + } + + function isRunning(d?: boolean) { + if (typeof d === 'boolean') { + state.isRunning = d; + } else { + return state.isRunning; + } + } + + function sampleProbability(d?: number) { + if (typeof d === 'number') { + state.sampleProbability = d; + } else { + return state.sampleProbability; + } + } + + function shouldStop(d?: boolean) { + if (typeof d === 'boolean') { + state.shouldStop = d; + } else { + return state.shouldStop; + } + } + + return { groupingEnabled, isRunning, loaded, sampleProbability, shouldStop }; +}; + +export type StateHandler = ReturnType; diff --git a/x-pack/plugins/aiops/server/routes/log_rate_analysis/response_stream_utils/stream_end.ts b/x-pack/plugins/aiops/server/routes/log_rate_analysis/response_stream_utils/stream_end.ts new file mode 100644 index 0000000000000..1be099d39a95e --- /dev/null +++ b/x-pack/plugins/aiops/server/routes/log_rate_analysis/response_stream_utils/stream_end.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 type { LogDebugMessage } from './log_debug_message'; +import type { StateHandler } from './state_handler'; + +/** + * Helper function that will check if the actual stream is still running + * and only then will call the callback to end the raw stream and update its state. + * This is implemented as a factory that receives the necessary dependencies + * which then returns the actual helper function. + */ +export const streamEndFactory = ( + stateHandler: StateHandler, + streamEndCallback: () => void, + logDebugMessage: LogDebugMessage +) => { + return function end() { + if (stateHandler.isRunning()) { + stateHandler.isRunning(false); + logDebugMessage('Ending analysis.'); + streamEndCallback(); + } else { + logDebugMessage('end() was called again with isRunning already being false.'); + } + }; +}; diff --git a/x-pack/plugins/aiops/server/routes/log_rate_analysis/response_stream_utils/stream_end_with_updated_loading_state.ts b/x-pack/plugins/aiops/server/routes/log_rate_analysis/response_stream_utils/stream_end_with_updated_loading_state.ts new file mode 100644 index 0000000000000..95957b9fed201 --- /dev/null +++ b/x-pack/plugins/aiops/server/routes/log_rate_analysis/response_stream_utils/stream_end_with_updated_loading_state.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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { i18n } from '@kbn/i18n'; + +import type { StreamFactoryReturnType } from '@kbn/ml-response-stream/server'; + +import { + updateLoadingStateAction, + type AiopsLogRateAnalysisApiAction, +} from '../../../../common/api/log_rate_analysis/actions'; +import type { AiopsLogRateAnalysisApiVersion as ApiVersion } from '../../../../common/api/log_rate_analysis/schema'; + +/** + * Helper function that will push a message to the stream that it's done and + * then run a callback to end the actual stream. + * This is implemented as a factory that receives the necessary dependencies + * which then returns the actual helper function. + */ +export const streamEndWithUpdatedLoadingStateFactory = ( + streamEndCallback: () => void, + push: StreamFactoryReturnType>['push'] +) => { + return function endWithUpdatedLoadingState() { + push( + updateLoadingStateAction({ + ccsWarning: false, + loaded: 1, + loadingState: i18n.translate('xpack.aiops.logRateAnalysis.loadingState.doneMessage', { + defaultMessage: 'Done.', + }), + }) + ); + + streamEndCallback(); + }; +}; diff --git a/x-pack/plugins/aiops/server/routes/log_rate_analysis/response_stream_utils/stream_push_error.ts b/x-pack/plugins/aiops/server/routes/log_rate_analysis/response_stream_utils/stream_push_error.ts new file mode 100644 index 0000000000000..74e10c3125a59 --- /dev/null +++ b/x-pack/plugins/aiops/server/routes/log_rate_analysis/response_stream_utils/stream_push_error.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 type { StreamFactoryReturnType } from '@kbn/ml-response-stream/server'; + +import type { AiopsLogRateAnalysisApiVersion as ApiVersion } from '../../../../common/api/log_rate_analysis/schema'; + +import type { LogDebugMessage } from './log_debug_message'; + +import { + addErrorAction, + type AiopsLogRateAnalysisApiAction, +} from '../../../../common/api/log_rate_analysis/actions'; + +/** + * Helper function that will push an error message to the stream. + * This is implemented as a factory that receives the necessary dependencies + * which then returns the actual helper function. + */ +export const streamPushErrorFactory = ( + push: StreamFactoryReturnType>['push'], + logDebugMessage: LogDebugMessage +) => { + return function pushError(m: string) { + logDebugMessage('Push error.'); + push(addErrorAction(m)); + }; +}; diff --git a/x-pack/plugins/aiops/server/routes/log_rate_analysis/response_stream_utils/stream_push_ping_with_timeout.ts b/x-pack/plugins/aiops/server/routes/log_rate_analysis/response_stream_utils/stream_push_ping_with_timeout.ts new file mode 100644 index 0000000000000..d3c03556c0ad6 --- /dev/null +++ b/x-pack/plugins/aiops/server/routes/log_rate_analysis/response_stream_utils/stream_push_ping_with_timeout.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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type { StreamFactoryReturnType } from '@kbn/ml-response-stream/server'; + +import { + pingAction, + type AiopsLogRateAnalysisApiAction, +} from '../../../../common/api/log_rate_analysis/actions'; +import type { AiopsLogRateAnalysisApiVersion as ApiVersion } from '../../../../common/api/log_rate_analysis/schema'; + +import type { LogDebugMessage } from './log_debug_message'; +import type { StateHandler } from './state_handler'; + +// 10s ping frequency to keep the stream alive. +const PING_FREQUENCY = 10000; + +/** + * Helper function that will push a ping message every 10s until the stream finishes. + * This is implemented as a factory that receives the necessary dependencies + * which then returns the actual helper function. + */ +export const streamPushPingWithTimeoutFactory = ( + stateHandler: StateHandler, + push: StreamFactoryReturnType>['push'], + logDebugMessage: LogDebugMessage +) => { + return function pushPingWithTimeout() { + setTimeout(() => { + if (stateHandler.isRunning()) { + logDebugMessage('Ping message.'); + push(pingAction()); + pushPingWithTimeout(); + } + }, PING_FREQUENCY); + }; +}; diff --git a/x-pack/plugins/aiops/server/routes/log_rate_analysis/route_handler_factory.ts b/x-pack/plugins/aiops/server/routes/log_rate_analysis/route_handler_factory.ts index 30f3dbe55f446..3c1bcde38ebd6 100644 --- a/x-pack/plugins/aiops/server/routes/log_rate_analysis/route_handler_factory.ts +++ b/x-pack/plugins/aiops/server/routes/log_rate_analysis/route_handler_factory.ts @@ -5,10 +5,6 @@ * 2.0. */ -import { queue } from 'async'; - -import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; - import type { CoreStart, KibanaRequest, @@ -17,67 +13,30 @@ import type { KibanaResponseFactory, } from '@kbn/core/server'; import type { Logger } from '@kbn/logging'; -import { i18n } from '@kbn/i18n'; -import { KBN_FIELD_TYPES } from '@kbn/field-types'; -import { streamFactory } from '@kbn/ml-response-stream/server'; -import type { - SignificantItem, - SignificantItemGroup, - SignificantItemHistogramItem, - NumericChartData, - NumericHistogramField, -} from '@kbn/ml-agg-utils'; -import { SIGNIFICANT_ITEM_TYPE } from '@kbn/ml-agg-utils'; -import { fetchHistogramsForFields } from '@kbn/ml-agg-utils'; import { createExecutionContext } from '@kbn/ml-route-utils'; import type { UsageCounter } from '@kbn/usage-collection-plugin/server'; -import { RANDOM_SAMPLER_SEED, AIOPS_TELEMETRY_ID } from '../../../common/constants'; -import { - addSignificantItemsAction, - addSignificantItemsGroupAction, - addSignificantItemsGroupHistogramAction, - addSignificantItemsHistogramAction, - addErrorAction, - pingAction, - resetAllAction, - resetErrorsAction, - resetGroupsAction, - updateLoadingStateAction, - AiopsLogRateAnalysisApiAction, -} from '../../../common/api/log_rate_analysis/actions'; +import { AIOPS_TELEMETRY_ID } from '../../../common/constants'; import type { AiopsLogRateAnalysisSchema, AiopsLogRateAnalysisApiVersion as ApiVersion, } from '../../../common/api/log_rate_analysis/schema'; -import { getCategoryQuery } from '../../../common/api/log_categorization/get_category_query'; import { AIOPS_API_ENDPOINT } from '../../../common/api'; import { PLUGIN_ID } from '../../../common'; import { isRequestAbortedError } from '../../lib/is_request_aborted_error'; -import type { AiopsLicense } from '../../types'; - -import { fetchSignificantCategories } from './queries/fetch_significant_categories'; -import { fetchSignificantTermPValues } from './queries/fetch_significant_term_p_values'; -import { fetchIndexInfo } from './queries/fetch_index_info'; -import { fetchFrequentItemSets } from './queries/fetch_frequent_item_sets'; -import { fetchTerms2CategoriesCounts } from './queries/fetch_terms_2_categories_counts'; -import { getHistogramQuery } from './queries/get_histogram_query'; -import { getGroupFilter } from './queries/get_group_filter'; -import { getSignificantItemGroups } from './queries/get_significant_item_groups'; import { trackAIOpsRouteUsage } from '../../lib/track_route_usage'; +import type { AiopsLicense } from '../../types'; -// 10s ping frequency to keep the stream alive. -const PING_FREQUENCY = 10000; - -// Overall progress is a float from 0 to 1. -const LOADED_FIELD_CANDIDATES = 0.2; -const PROGRESS_STEP_P_VALUES = 0.5; -const PROGRESS_STEP_GROUPING = 0.1; -const PROGRESS_STEP_HISTOGRAMS = 0.1; -const PROGRESS_STEP_HISTOGRAMS_GROUPS = 0.1; +import { responseStreamFactory } from './response_stream_factory'; +import { PROGRESS_STEP_HISTOGRAMS_GROUPS } from './response_stream_utils/constants'; +/** + * The log rate analysis route handler sets up `responseStreamFactory` + * to create the response stream and then uses its handlers to + * walk through the steps of the analysis. + */ export function routeHandlerFactory( version: T, license: AiopsLicense, @@ -106,814 +65,71 @@ export function routeHandlerFactory( const executionContext = createExecutionContext(coreStart, PLUGIN_ID, request.route.path); return await coreStart.executionContext.withContext(executionContext, () => { - let logMessageCounter = 1; - - function logDebugMessage(msg: string) { - logger.debug(`Log Rate Analysis #${logMessageCounter}: ${msg}`); - logMessageCounter++; - } - - logDebugMessage('Starting analysis.'); - - const groupingEnabled = !!request.body.grouping; - const sampleProbability = request.body.sampleProbability ?? 1; - - const controller = new AbortController(); - const abortSignal = controller.signal; - - let isRunning = false; - let loaded = 0; - let shouldStop = false; - request.events.aborted$.subscribe(() => { - logDebugMessage('aborted$ subscription trigger.'); - shouldStop = true; - controller.abort(); - }); - request.events.completed$.subscribe(() => { - logDebugMessage('completed$ subscription trigger.'); - shouldStop = true; - controller.abort(); - }); - - const { - end: streamEnd, - push, - responseWithHeaders, - } = streamFactory>( - request.headers, - logger, - request.body.compressResponse, - request.body.flushFix - ); - - function pushPingWithTimeout() { - setTimeout(() => { - if (isRunning) { - logDebugMessage('Ping message.'); - push(pingAction()); - pushPingWithTimeout(); - } - }, PING_FREQUENCY); - } - - function end() { - if (isRunning) { - isRunning = false; - logDebugMessage('Ending analysis.'); - streamEnd(); - } else { - logDebugMessage('end() was called again with isRunning already being false.'); - } - } - - function endWithUpdatedLoadingState() { - push( - updateLoadingStateAction({ - ccsWarning: false, - loaded: 1, - loadingState: i18n.translate('xpack.aiops.logRateAnalysis.loadingState.doneMessage', { - defaultMessage: 'Done.', - }), - }) - ); - - end(); - } - - function pushError(m: string) { - logDebugMessage('Push error.'); - push(addErrorAction(m)); - } + const { analysis, logDebugMessage, stateHandler, responseStream, responseWithHeaders } = + responseStreamFactory({ + version, + client, + requestBody: request.body, + events: request.events, + headers: request.headers, + logger, + }); async function runAnalysis() { try { - isRunning = true; - - if (!request.body.overrides) { - logDebugMessage('Full Reset.'); - push(resetAllAction()); - } else { - logDebugMessage('Reset Errors.'); - push(resetErrorsAction()); - } - - if (request.body.overrides?.regroupOnly) { - logDebugMessage('Reset Groups.'); - push(resetGroupsAction()); - } - - if (request.body.overrides?.loaded) { - logDebugMessage(`Set 'loaded' override to '${request.body.overrides?.loaded}'.`); - loaded = request.body.overrides?.loaded; - } + logDebugMessage('Starting analysis.'); + logDebugMessage(`Sample probability: ${stateHandler.sampleProbability()}`); - pushPingWithTimeout(); + stateHandler.isRunning(true); + analysis.overridesHandler(); + responseStream.pushPingWithTimeout(); // Step 1: Index Info: Field candidates, total doc count, sample probability + const indexInfo = await analysis.indexInfoHandler(); - const fieldCandidates: string[] = []; - let fieldCandidatesCount = fieldCandidates.length; - - const textFieldCandidates: string[] = []; - - let totalDocCount = 0; - - if (!request.body.overrides?.remainingFieldCandidates) { - logDebugMessage('Fetch index information.'); - push( - updateLoadingStateAction({ - ccsWarning: false, - loaded, - loadingState: i18n.translate( - 'xpack.aiops.logRateAnalysis.loadingState.loadingIndexInformation', - { - defaultMessage: 'Loading index information.', - } - ), - }) - ); - - try { - const indexInfo = await fetchIndexInfo( - client, - request.body, - ['message', 'error.message'], - abortSignal - ); - - fieldCandidates.push(...indexInfo.fieldCandidates); - fieldCandidatesCount = fieldCandidates.length; - textFieldCandidates.push(...indexInfo.textFieldCandidates); - totalDocCount = indexInfo.totalDocCount; - } catch (e) { - if (!isRequestAbortedError(e)) { - logger.error(`Failed to fetch index information, got: \n${e.toString()}`); - pushError(`Failed to fetch index information.`); - } - end(); - return; - } - - logDebugMessage(`Total document count: ${totalDocCount}`); - logDebugMessage(`Sample probability: ${sampleProbability}`); - - loaded += LOADED_FIELD_CANDIDATES; - - pushPingWithTimeout(); - - push( - updateLoadingStateAction({ - ccsWarning: false, - loaded, - loadingState: i18n.translate( - 'xpack.aiops.logRateAnalysis.loadingState.identifiedFieldCandidates', - { - defaultMessage: - 'Identified {fieldCandidatesCount, plural, one {# field candidate} other {# field candidates}}.', - values: { - fieldCandidatesCount, - }, - } - ), - }) - ); - - if (fieldCandidatesCount === 0) { - endWithUpdatedLoadingState(); - } else if (shouldStop) { - logDebugMessage('shouldStop after fetching field candidates.'); - end(); - return; - } - } - - // Step 2: Significant Categories and Items - - // This will store the combined count of detected significant log patterns and keywords - let fieldValuePairsCount = 0; - - const significantCategories: SignificantItem[] = []; - - if (version === '1') { - significantCategories.push( - ...(( - request.body as AiopsLogRateAnalysisSchema<'1'> - ).overrides?.significantTerms?.filter( - (d) => d.type === SIGNIFICANT_ITEM_TYPE.LOG_PATTERN - ) ?? []) - ); - } - - if (version === '2') { - significantCategories.push( - ...(( - request.body as AiopsLogRateAnalysisSchema<'2'> - ).overrides?.significantItems?.filter( - (d) => d.type === SIGNIFICANT_ITEM_TYPE.LOG_PATTERN - ) ?? []) - ); - } - - // Get significant categories of text fields - if (textFieldCandidates.length > 0) { - significantCategories.push( - ...(await fetchSignificantCategories( - client, - request.body, - textFieldCandidates, - logger, - sampleProbability, - pushError, - abortSignal - )) - ); - - if (significantCategories.length > 0) { - push(addSignificantItemsAction(significantCategories, version)); - } - } - - const significantTerms: SignificantItem[] = []; - - if (version === '1') { - significantTerms.push( - ...(( - request.body as AiopsLogRateAnalysisSchema<'1'> - ).overrides?.significantTerms?.filter( - (d) => d.type === SIGNIFICANT_ITEM_TYPE.KEYWORD - ) ?? []) - ); - } - - if (version === '2') { - significantTerms.push( - ...(( - request.body as AiopsLogRateAnalysisSchema<'2'> - ).overrides?.significantItems?.filter( - (d) => d.type === SIGNIFICANT_ITEM_TYPE.KEYWORD - ) ?? []) - ); - } - - const fieldsToSample = new Set(); - - // Don't use more than 10 here otherwise Kibana will emit an error - // regarding a limit of abort signal listeners of more than 10. - const MAX_CONCURRENT_QUERIES = 10; - - let remainingFieldCandidates: string[]; - let loadingStepSizePValues = PROGRESS_STEP_P_VALUES; - - if (request.body.overrides?.remainingFieldCandidates) { - fieldCandidates.push(...request.body.overrides?.remainingFieldCandidates); - remainingFieldCandidates = request.body.overrides?.remainingFieldCandidates; - fieldCandidatesCount = fieldCandidates.length; - loadingStepSizePValues = - LOADED_FIELD_CANDIDATES + - PROGRESS_STEP_P_VALUES - - (request.body.overrides?.loaded ?? PROGRESS_STEP_P_VALUES); - } else { - remainingFieldCandidates = fieldCandidates; - } - - logDebugMessage('Fetch p-values.'); - - const pValuesQueue = queue(async function (fieldCandidate: string) { - loaded += (1 / fieldCandidatesCount) * loadingStepSizePValues; - - let pValues: Awaited>; - - try { - pValues = await fetchSignificantTermPValues( - client, - request.body, - [fieldCandidate], - logger, - sampleProbability, - pushError, - abortSignal - ); - } catch (e) { - if (!isRequestAbortedError(e)) { - logger.error( - `Failed to fetch p-values for '${fieldCandidate}', got: \n${e.toString()}` - ); - pushError(`Failed to fetch p-values for '${fieldCandidate}'.`); - } - return; - } - - remainingFieldCandidates = remainingFieldCandidates.filter((d) => d !== fieldCandidate); - - if (pValues.length > 0) { - pValues.forEach((d) => { - fieldsToSample.add(d.fieldName); - }); - significantTerms.push(...pValues); - - push(addSignificantItemsAction(pValues, version)); - } - - push( - updateLoadingStateAction({ - ccsWarning: false, - loaded, - loadingState: i18n.translate( - 'xpack.aiops.logRateAnalysis.loadingState.identifiedFieldValuePairs', - { - defaultMessage: - 'Identified {fieldValuePairsCount, plural, one {# significant field/value pair} other {# significant field/value pairs}}.', - values: { - fieldValuePairsCount, - }, - } - ), - remainingFieldCandidates, - }) - ); - }, MAX_CONCURRENT_QUERIES); - - pValuesQueue.push(fieldCandidates, (err) => { - if (err) { - logger.error(`Failed to fetch p-values.', got: \n${err.toString()}`); - pushError(`Failed to fetch p-values.`); - pValuesQueue.kill(); - end(); - } else if (shouldStop) { - logDebugMessage('shouldStop fetching p-values.'); - pValuesQueue.kill(); - end(); - } - }); - await pValuesQueue.drain(); - - fieldValuePairsCount = significantCategories.length + significantTerms.length; - - if (fieldValuePairsCount === 0) { - logDebugMessage('Stopping analysis, did not find significant terms.'); - endWithUpdatedLoadingState(); + if (!indexInfo) { return; } - const histogramFields: [NumericHistogramField] = [ - { fieldName: request.body.timeFieldName, type: KBN_FIELD_TYPES.DATE }, - ]; - - logDebugMessage('Fetch overall histogram.'); - - let overallTimeSeries: NumericChartData | undefined; - - const overallHistogramQuery = getHistogramQuery(request.body); - - try { - overallTimeSeries = ( - (await fetchHistogramsForFields( - client, - request.body.index, - overallHistogramQuery, - // fields - histogramFields, - // samplerShardSize - -1, - undefined, - abortSignal, - sampleProbability, - RANDOM_SAMPLER_SEED - )) as [NumericChartData] - )[0]; - } catch (e) { - if (!isRequestAbortedError(e)) { - logger.error(`Failed to fetch the overall histogram data, got: \n${e.toString()}`); - pushError(`Failed to fetch overall histogram data.`); - } - // Still continue the analysis even if loading the overall histogram fails. - } - - function pushHistogramDataLoadingState() { - push( - updateLoadingStateAction({ - ccsWarning: false, - loaded, - loadingState: i18n.translate( - 'xpack.aiops.logRateAnalysis.loadingState.loadingHistogramData', - { - defaultMessage: 'Loading histogram data.', - } - ), - }) - ); - } + // Step 2: Significant categories and terms + const significantItemsObj = await analysis.significantItemsHandler(indexInfo); - if (shouldStop) { - logDebugMessage('shouldStop after fetching overall histogram.'); - end(); + if (!significantItemsObj) { return; } - if (groupingEnabled) { - logDebugMessage('Group results.'); - - push( - updateLoadingStateAction({ - ccsWarning: false, - loaded, - loadingState: i18n.translate( - 'xpack.aiops.logRateAnalysis.loadingState.groupingResults', - { - defaultMessage: 'Transforming significant field/value pairs into groups.', - } - ), - groupsMissing: true, - }) - ); - - try { - const { fields, itemSets } = await fetchFrequentItemSets( - client, - request.body.index, - JSON.parse(request.body.searchQuery) as estypes.QueryDslQueryContainer, - significantTerms, - request.body.timeFieldName, - request.body.deviationMin, - request.body.deviationMax, - logger, - sampleProbability, - pushError, - abortSignal - ); - - if (significantCategories.length > 0 && significantTerms.length > 0) { - const { - fields: significantCategoriesFields, - itemSets: significantCategoriesItemSets, - } = await fetchTerms2CategoriesCounts( - client, - request.body, - JSON.parse(request.body.searchQuery) as estypes.QueryDslQueryContainer, - significantTerms, - itemSets, - significantCategories, - request.body.deviationMin, - request.body.deviationMax, - logger, - pushError, - abortSignal - ); - - fields.push(...significantCategoriesFields); - itemSets.push(...significantCategoriesItemSets); - } - - if (shouldStop) { - logDebugMessage('shouldStop after fetching frequent_item_sets.'); - end(); - return; - } - - if (fields.length > 0 && itemSets.length > 0) { - const significantItemGroups = getSignificantItemGroups( - itemSets, - [...significantTerms, ...significantCategories], - fields - ); - - // We'll find out if there's at least one group with at least two items, - // only then will we return the groups to the clients and make the grouping option available. - const maxItems = Math.max(...significantItemGroups.map((g) => g.group.length)); - - if (maxItems > 1) { - push(addSignificantItemsGroupAction(significantItemGroups, version)); - } - - loaded += PROGRESS_STEP_GROUPING; - - pushHistogramDataLoadingState(); - - if (shouldStop) { - logDebugMessage('shouldStop after grouping.'); - end(); - return; - } - - logDebugMessage(`Fetch ${significantItemGroups.length} group histograms.`); - - const groupHistogramQueue = queue(async function (cpg: SignificantItemGroup) { - if (shouldStop) { - logDebugMessage('shouldStop abort fetching group histograms.'); - groupHistogramQueue.kill(); - end(); - return; - } - - if (overallTimeSeries !== undefined) { - const histogramQuery = getHistogramQuery(request.body, getGroupFilter(cpg)); - - let cpgTimeSeries: NumericChartData; - try { - cpgTimeSeries = ( - (await fetchHistogramsForFields( - client, - request.body.index, - histogramQuery, - // fields - [ - { - fieldName: request.body.timeFieldName, - type: KBN_FIELD_TYPES.DATE, - interval: overallTimeSeries.interval, - min: overallTimeSeries.stats[0], - max: overallTimeSeries.stats[1], - }, - ], - // samplerShardSize - -1, - undefined, - abortSignal, - sampleProbability, - RANDOM_SAMPLER_SEED - )) as [NumericChartData] - )[0]; - } catch (e) { - if (!isRequestAbortedError(e)) { - logger.error( - `Failed to fetch the histogram data for group #${ - cpg.id - }, got: \n${e.toString()}` - ); - pushError(`Failed to fetch the histogram data for group #${cpg.id}.`); - } - return; - } - const histogram: SignificantItemHistogramItem[] = - overallTimeSeries.data.map((o) => { - const current = cpgTimeSeries.data.find( - (d1) => d1.key_as_string === o.key_as_string - ) ?? { - doc_count: 0, - }; - - if (version === '1') { - return { - key: o.key, - key_as_string: o.key_as_string ?? '', - doc_count_significant_term: current.doc_count, - doc_count_overall: Math.max(0, o.doc_count - current.doc_count), - }; - } - - return { - key: o.key, - key_as_string: o.key_as_string ?? '', - doc_count_significant_item: current.doc_count, - doc_count_overall: Math.max(0, o.doc_count - current.doc_count), - }; - }) ?? []; - - push( - addSignificantItemsGroupHistogramAction( - [ - { - id: cpg.id, - histogram, - }, - ], - version - ) - ); - } - }, MAX_CONCURRENT_QUERIES); - - groupHistogramQueue.push(significantItemGroups); - await groupHistogramQueue.drain(); - } - } catch (e) { - if (!isRequestAbortedError(e)) { - logger.error( - `Failed to transform field/value pairs into groups, got: \n${e.toString()}` - ); - pushError(`Failed to transform field/value pairs into groups.`); - } - } - } - - loaded += PROGRESS_STEP_HISTOGRAMS_GROUPS; + const { fieldValuePairsCount, significantCategories, significantTerms } = + significantItemsObj; - logDebugMessage(`Fetch ${significantTerms.length} field/value histograms.`); + // Step 3: Fetch overall histogram + const overallTimeSeries = await analysis.overallHistogramHandler(); - // time series filtered by fields - if ( - significantTerms.length > 0 && - overallTimeSeries !== undefined && - !request.body.overrides?.regroupOnly - ) { - const fieldValueHistogramQueue = queue(async function (cp: SignificantItem) { - if (shouldStop) { - logDebugMessage('shouldStop abort fetching field/value histograms.'); - fieldValueHistogramQueue.kill(); - end(); - return; - } - - if (overallTimeSeries !== undefined) { - const histogramQuery = getHistogramQuery(request.body, [ - { - term: { [cp.fieldName]: cp.fieldValue }, - }, - ]); - - let cpTimeSeries: NumericChartData; - - try { - cpTimeSeries = ( - (await fetchHistogramsForFields( - client, - request.body.index, - histogramQuery, - // fields - [ - { - fieldName: request.body.timeFieldName, - type: KBN_FIELD_TYPES.DATE, - interval: overallTimeSeries.interval, - min: overallTimeSeries.stats[0], - max: overallTimeSeries.stats[1], - }, - ], - // samplerShardSize - -1, - undefined, - abortSignal, - sampleProbability, - RANDOM_SAMPLER_SEED - )) as [NumericChartData] - )[0]; - } catch (e) { - logger.error( - `Failed to fetch the histogram data for field/value pair "${cp.fieldName}:${ - cp.fieldValue - }", got: \n${e.toString()}` - ); - pushError( - `Failed to fetch the histogram data for field/value pair "${cp.fieldName}:${cp.fieldValue}".` - ); - return; - } - - const histogram: SignificantItemHistogramItem[] = - overallTimeSeries.data.map((o) => { - const current = cpTimeSeries.data.find( - (d1) => d1.key_as_string === o.key_as_string - ) ?? { - doc_count: 0, - }; - if (version === '1') { - return { - key: o.key, - key_as_string: o.key_as_string ?? '', - doc_count_significant_term: current.doc_count, - doc_count_overall: Math.max(0, o.doc_count - current.doc_count), - }; - } - - return { - key: o.key, - key_as_string: o.key_as_string ?? '', - doc_count_significant_item: current.doc_count, - doc_count_overall: Math.max(0, o.doc_count - current.doc_count), - }; - }) ?? []; - - const { fieldName, fieldValue } = cp; - - loaded += (1 / fieldValuePairsCount) * PROGRESS_STEP_HISTOGRAMS; - pushHistogramDataLoadingState(); - push( - addSignificantItemsHistogramAction( - [ - { - fieldName, - fieldValue, - histogram, - }, - ], - version - ) - ); - } - }, MAX_CONCURRENT_QUERIES); - - fieldValueHistogramQueue.push(significantTerms); - await fieldValueHistogramQueue.drain(); + // Step 4: Smart gropuing + if (stateHandler.groupingEnabled()) { + await analysis.groupingHandler( + significantCategories, + significantTerms, + overallTimeSeries + ); } - // histograms for text field patterns - if ( - overallTimeSeries !== undefined && - significantCategories.length > 0 && - !request.body.overrides?.regroupOnly - ) { - const significantCategoriesHistogramQueries = significantCategories.map((d) => { - const histogramQuery = getHistogramQuery(request.body); - const categoryQuery = getCategoryQuery(d.fieldName, [ - { key: `${d.key}`, count: d.doc_count, examples: [] }, - ]); - if (Array.isArray(histogramQuery.bool?.filter)) { - histogramQuery.bool?.filter?.push(categoryQuery); - } - return histogramQuery; - }); - - for (const [i, histogramQuery] of significantCategoriesHistogramQueries.entries()) { - const cp = significantCategories[i]; - let catTimeSeries: NumericChartData; - - try { - catTimeSeries = ( - (await fetchHistogramsForFields( - client, - request.body.index, - histogramQuery, - // fields - [ - { - fieldName: request.body.timeFieldName, - type: KBN_FIELD_TYPES.DATE, - interval: overallTimeSeries.interval, - min: overallTimeSeries.stats[0], - max: overallTimeSeries.stats[1], - }, - ], - // samplerShardSize - -1, - undefined, - abortSignal, - sampleProbability, - RANDOM_SAMPLER_SEED - )) as [NumericChartData] - )[0]; - } catch (e) { - logger.error( - `Failed to fetch the histogram data for field/value pair "${cp.fieldName}:${ - cp.fieldValue - }", got: \n${e.toString()}` - ); - pushError( - `Failed to fetch the histogram data for field/value pair "${cp.fieldName}:${cp.fieldValue}".` - ); - return; - } - - const histogram: SignificantItemHistogramItem[] = - overallTimeSeries.data.map((o) => { - const current = catTimeSeries.data.find( - (d1) => d1.key_as_string === o.key_as_string - ) ?? { - doc_count: 0, - }; + stateHandler.loaded(PROGRESS_STEP_HISTOGRAMS_GROUPS, false); - if (version === '1') { - return { - key: o.key, - key_as_string: o.key_as_string ?? '', - doc_count_significant_term: current.doc_count, - doc_count_overall: Math.max(0, o.doc_count - current.doc_count), - }; - } - - return { - key: o.key, - key_as_string: o.key_as_string ?? '', - doc_count_significant_item: current.doc_count, - doc_count_overall: Math.max(0, o.doc_count - current.doc_count), - }; - }) ?? []; - - const { fieldName, fieldValue } = cp; - - loaded += (1 / fieldValuePairsCount) * PROGRESS_STEP_HISTOGRAMS; - pushHistogramDataLoadingState(); - push( - addSignificantItemsHistogramAction( - [ - { - fieldName, - fieldValue, - histogram, - }, - ], - version - ) - ); - } - } + // Step 5: Histograms + await analysis.histogramHandler( + fieldValuePairsCount, + significantCategories, + significantTerms, + overallTimeSeries + ); - endWithUpdatedLoadingState(); + responseStream.endWithUpdatedLoadingState(); } catch (e) { if (!isRequestAbortedError(e)) { logger.error(`Log Rate Analysis failed to finish, got: \n${e.toString()}`); - pushError(`Log Rate Analysis failed to finish.`); + responseStream.pushError(`Log Rate Analysis failed to finish.`); } - end(); + responseStream.end(); } } diff --git a/x-pack/plugins/aiops/tsconfig.json b/x-pack/plugins/aiops/tsconfig.json index 67e8908f5c421..31d68a5a4ab0f 100644 --- a/x-pack/plugins/aiops/tsconfig.json +++ b/x-pack/plugins/aiops/tsconfig.json @@ -23,7 +23,6 @@ "@kbn/data-views-plugin", "@kbn/datemath", "@kbn/es-query", - "@kbn/es-types", "@kbn/field-formats-plugin", "@kbn/field-types", "@kbn/i18n-react", @@ -66,6 +65,7 @@ "@kbn/ml-chi2test", "@kbn/usage-collection-plugin", "@kbn/analytics", + "@kbn/core-http-server", ], "exclude": [ "target/**/*", diff --git a/x-pack/plugins/alerting/common/routes/rule/apis/create/schemas/v1.ts b/x-pack/plugins/alerting/common/routes/rule/apis/create/schemas/v1.ts index e471dd3cea530..751f2e8c38780 100644 --- a/x-pack/plugins/alerting/common/routes/rule/apis/create/schemas/v1.ts +++ b/x-pack/plugins/alerting/common/routes/rule/apis/create/schemas/v1.ts @@ -8,6 +8,7 @@ import { schema } from '@kbn/config-schema'; import { validateDurationV1, validateHoursV1, validateTimezoneV1 } from '../../../validation'; import { notifyWhenSchemaV1 } from '../../../response'; +import { filterStateStore } from '../../../common/constants/v1'; export const actionFrequencySchema = schema.object({ summary: schema.boolean(), @@ -23,7 +24,14 @@ export const actionAlertsFilterSchema = schema.object({ schema.object({ query: schema.maybe(schema.recordOf(schema.string(), schema.any())), meta: schema.recordOf(schema.string(), schema.any()), - state$: schema.maybe(schema.object({ store: schema.string() })), + $state: schema.maybe( + schema.object({ + store: schema.oneOf([ + schema.literal(filterStateStore.APP_STATE), + schema.literal(filterStateStore.GLOBAL_STATE), + ]), + }) + ), }) ), dsl: schema.maybe(schema.string()), @@ -63,6 +71,7 @@ export const actionSchema = schema.object({ params: schema.recordOf(schema.string(), schema.maybe(schema.any()), { defaultValue: {} }), frequency: schema.maybe(actionFrequencySchema), alerts_filter: schema.maybe(actionAlertsFilterSchema), + use_alert_data_for_template: schema.maybe(schema.boolean()), }); export const createBodySchema = schema.object({ diff --git a/x-pack/plugins/alerting/common/routes/rule/common/constants/v1.ts b/x-pack/plugins/alerting/common/routes/rule/common/constants/v1.ts index fbeb08ba6bc7f..3bf7208efe37f 100644 --- a/x-pack/plugins/alerting/common/routes/rule/common/constants/v1.ts +++ b/x-pack/plugins/alerting/common/routes/rule/common/constants/v1.ts @@ -43,6 +43,11 @@ export const ruleExecutionStatusWarningReason = { MAX_QUEUED_ACTIONS: 'maxQueuedActions', } as const; +export const filterStateStore = { + APP_STATE: 'appState', + GLOBAL_STATE: 'globalState', +} as const; + export type RuleNotifyWhen = typeof ruleNotifyWhen[keyof typeof ruleNotifyWhen]; export type RuleLastRunOutcomeValues = typeof ruleLastRunOutcomeValues[keyof typeof ruleLastRunOutcomeValues]; @@ -52,3 +57,4 @@ export type RuleExecutionStatusErrorReason = typeof ruleExecutionStatusErrorReason[keyof typeof ruleExecutionStatusErrorReason]; export type RuleExecutionStatusWarningReason = typeof ruleExecutionStatusWarningReason[keyof typeof ruleExecutionStatusWarningReason]; +export type FilterStateStore = typeof filterStateStore[keyof typeof filterStateStore]; diff --git a/x-pack/plugins/alerting/common/routes/rule/common/index.ts b/x-pack/plugins/alerting/common/routes/rule/common/index.ts index 5989a3a993e7a..669bfc484070a 100644 --- a/x-pack/plugins/alerting/common/routes/rule/common/index.ts +++ b/x-pack/plugins/alerting/common/routes/rule/common/index.ts @@ -11,6 +11,7 @@ export { ruleExecutionStatusValues, ruleExecutionStatusErrorReason, ruleExecutionStatusWarningReason, + filterStateStore, } from './constants/latest'; export type { @@ -19,6 +20,7 @@ export type { RuleExecutionStatusValues, RuleExecutionStatusErrorReason, RuleExecutionStatusWarningReason, + FilterStateStore, } from './constants/latest'; export { @@ -27,6 +29,7 @@ export { ruleExecutionStatusValues as ruleExecutionStatusValuesV1, ruleExecutionStatusErrorReason as ruleExecutionStatusErrorReasonV1, ruleExecutionStatusWarningReason as ruleExecutionStatusWarningReasonV1, + filterStateStore as filterStateStoreV1, } from './constants/v1'; export type { @@ -35,4 +38,5 @@ export type { RuleExecutionStatusValues as RuleExecutionStatusValuesV1, RuleExecutionStatusErrorReason as RuleExecutionStatusErrorReasonV1, RuleExecutionStatusWarningReason as RuleExecutionStatusWarningReasonV1, + FilterStateStore as FilterStateStoreV1, } from './constants/v1'; diff --git a/x-pack/plugins/alerting/common/routes/rule/response/schemas/v1.ts b/x-pack/plugins/alerting/common/routes/rule/response/schemas/v1.ts index fe02146c5ef62..0e043aa217667 100644 --- a/x-pack/plugins/alerting/common/routes/rule/response/schemas/v1.ts +++ b/x-pack/plugins/alerting/common/routes/rule/response/schemas/v1.ts @@ -13,6 +13,7 @@ import { ruleExecutionStatusErrorReason as ruleExecutionStatusErrorReasonV1, ruleExecutionStatusWarningReason as ruleExecutionStatusWarningReasonV1, ruleLastRunOutcomeValues as ruleLastRunOutcomeValuesV1, + filterStateStore as filterStateStoreV1, } from '../../common/constants/v1'; import { validateNotifyWhenV1 } from '../../validation'; @@ -47,7 +48,14 @@ const actionAlertsFilterSchema = schema.object({ schema.object({ query: schema.maybe(schema.recordOf(schema.string(), schema.any())), meta: schema.recordOf(schema.string(), schema.any()), - state$: schema.maybe(schema.object({ store: schema.string() })), + $state: schema.maybe( + schema.object({ + store: schema.oneOf([ + schema.literal(filterStateStoreV1.APP_STATE), + schema.literal(filterStateStoreV1.GLOBAL_STATE), + ]), + }) + ), }) ), }) diff --git a/x-pack/plugins/alerting/common/rule.ts b/x-pack/plugins/alerting/common/rule.ts index ff74752df8695..da3788d534598 100644 --- a/x-pack/plugins/alerting/common/rule.ts +++ b/x-pack/plugins/alerting/common/rule.ts @@ -116,6 +116,7 @@ export interface RuleAction { params: RuleActionParams; frequency?: RuleActionFrequency; alertsFilter?: AlertsFilter; + useAlertDataForTemplate?: boolean; } export interface RuleLastRun { diff --git a/x-pack/plugins/alerting/server/alert/alert.ts b/x-pack/plugins/alerting/server/alert/alert.ts index ee8c48a18447b..835b8db17a893 100644 --- a/x-pack/plugins/alerting/server/alert/alert.ts +++ b/x-pack/plugins/alerting/server/alert/alert.ts @@ -6,6 +6,7 @@ */ import { v4 as uuidV4 } from 'uuid'; +import { AADAlert } from '@kbn/alerts-as-data-utils'; import { get, isEmpty } from 'lodash'; import { MutableAlertInstanceMeta } from '@kbn/alerting-state-types'; import { ALERT_UUID } from '@kbn/rule-data-utils'; @@ -36,7 +37,7 @@ export type PublicAlert< Context extends AlertInstanceContext = AlertInstanceContext, ActionGroupIds extends string = DefaultActionGroupId > = Pick< - Alert, + Alert, | 'getContext' | 'getState' | 'getUuid' @@ -50,13 +51,15 @@ export type PublicAlert< export class Alert< State extends AlertInstanceState = AlertInstanceState, Context extends AlertInstanceContext = AlertInstanceContext, - ActionGroupIds extends string = never + ActionGroupIds extends string = never, + AlertAsData extends AADAlert = AADAlert > { private scheduledExecutionOptions?: ScheduledExecutionOptions; private meta: MutableAlertInstanceMeta; private state: State; private context: Context; private readonly id: string; + private alertAsData: AlertAsData | undefined; constructor(id: string, { state, meta = {} }: RawAlertInstance = {}) { this.id = id; @@ -78,6 +81,18 @@ export class Alert< return this.meta.uuid!; } + isAlertAsData() { + return this.alertAsData !== undefined; + } + + setAlertAsData(alertAsData: AlertAsData) { + this.alertAsData = alertAsData; + } + + getAlertAsData() { + return this.alertAsData; + } + getStart(): string | null { return this.state.start ? `${this.state.start}` : null; } diff --git a/x-pack/plugins/alerting/server/application/rule/constants.ts b/x-pack/plugins/alerting/server/application/rule/constants.ts index bc75d91375ecb..0881868d9db8f 100644 --- a/x-pack/plugins/alerting/server/application/rule/constants.ts +++ b/x-pack/plugins/alerting/server/application/rule/constants.ts @@ -42,3 +42,8 @@ export const ruleExecutionStatusWarningReason = { MAX_ALERTS: 'maxAlerts', MAX_QUEUED_ACTIONS: 'maxQueuedActions', } as const; + +export const filterStateStore = { + APP_STATE: 'appState', + GLOBAL_STATE: 'globalState', +} as const; diff --git a/x-pack/plugins/alerting/server/application/rule/methods/create/create_rule.ts b/x-pack/plugins/alerting/server/application/rule/methods/create/create_rule.ts index d774a80ae4ebc..74dd0775d0c22 100644 --- a/x-pack/plugins/alerting/server/application/rule/methods/create/create_rule.ts +++ b/x-pack/plugins/alerting/server/application/rule/methods/create/create_rule.ts @@ -23,7 +23,7 @@ import { } from '../../../../rules_client/lib'; import { generateAPIKeyName, apiKeyAsRuleDomainProperties } from '../../../../rules_client/common'; import { ruleAuditEvent, RuleAuditAction } from '../../../../rules_client/common/audit_events'; -import { RulesClientContext } from '../../../../rules_client/types'; +import { RulesClientContext, NormalizedAlertAction } from '../../../../rules_client/types'; import { RuleDomain, RuleParams } from '../../types'; import { SanitizedRule } from '../../../../types'; import { @@ -55,7 +55,11 @@ export async function createRule( ): Promise> { const { data: initialData, options, allowMissingConnectorSecrets } = createParams; - const data = { ...initialData, actions: addGeneratedActionValues(initialData.actions) }; + // TODO (http-versioning): Remove this cast when we fix addGeneratedActionValues + const data = { + ...initialData, + actions: addGeneratedActionValues(initialData.actions as NormalizedAlertAction[]), + }; const id = options?.id || SavedObjectsUtils.generateId(); diff --git a/x-pack/plugins/alerting/server/application/rule/methods/create/schemas/create_rule_data_schema.ts b/x-pack/plugins/alerting/server/application/rule/methods/create/schemas/create_rule_data_schema.ts index ce51e88c5ce73..b7e5591996957 100644 --- a/x-pack/plugins/alerting/server/application/rule/methods/create/schemas/create_rule_data_schema.ts +++ b/x-pack/plugins/alerting/server/application/rule/methods/create/schemas/create_rule_data_schema.ts @@ -35,6 +35,7 @@ export const createRuleDataSchema = schema.object({ ), uuid: schema.maybe(schema.string()), alertsFilter: schema.maybe(actionAlertsFilterSchema), + useAlertDataForTemplate: schema.maybe(schema.boolean()), }), { defaultValue: [] } ), diff --git a/x-pack/plugins/alerting/server/application/rule/schemas/action_schemas.ts b/x-pack/plugins/alerting/server/application/rule/schemas/action_schemas.ts index f123466eca1ab..579f41adb0424 100644 --- a/x-pack/plugins/alerting/server/application/rule/schemas/action_schemas.ts +++ b/x-pack/plugins/alerting/server/application/rule/schemas/action_schemas.ts @@ -7,6 +7,7 @@ import { schema } from '@kbn/config-schema'; import { notifyWhenSchema } from './notify_when_schema'; +import { filterStateStore } from '../constants'; export const actionParamsSchema = schema.recordOf(schema.string(), schema.maybe(schema.any())); @@ -14,7 +15,14 @@ const actionAlertsFilterQueryFiltersSchema = schema.arrayOf( schema.object({ query: schema.maybe(schema.recordOf(schema.string(), schema.any())), meta: schema.recordOf(schema.string(), schema.any()), - state$: schema.maybe(schema.object({ store: schema.string() })), + $state: schema.maybe( + schema.object({ + store: schema.oneOf([ + schema.literal(filterStateStore.APP_STATE), + schema.literal(filterStateStore.GLOBAL_STATE), + ]), + }) + ), }) ); @@ -65,6 +73,7 @@ export const actionDomainSchema = schema.object({ params: actionParamsSchema, frequency: schema.maybe(actionFrequencySchema), alertsFilter: schema.maybe(actionDomainAlertsFilterSchema), + useAlertDataAsTemplate: schema.maybe(schema.boolean()), }); /** @@ -89,4 +98,5 @@ export const actionSchema = schema.object({ params: actionParamsSchema, frequency: schema.maybe(actionFrequencySchema), alertsFilter: schema.maybe(actionAlertsFilterSchema), + useAlertDataForTemplate: schema.maybe(schema.boolean()), }); diff --git a/x-pack/plugins/alerting/server/application/rule/types/rule.ts b/x-pack/plugins/alerting/server/application/rule/types/rule.ts index 04e37a125aa40..d8dbabb72b23b 100644 --- a/x-pack/plugins/alerting/server/application/rule/types/rule.ts +++ b/x-pack/plugins/alerting/server/application/rule/types/rule.ts @@ -12,6 +12,7 @@ import { ruleExecutionStatusValues, ruleExecutionStatusErrorReason, ruleExecutionStatusWarningReason, + filterStateStore, } from '../constants'; import { ruleParamsSchema, @@ -33,6 +34,7 @@ export type RuleExecutionStatusErrorReason = typeof ruleExecutionStatusErrorReason[keyof typeof ruleExecutionStatusErrorReason]; export type RuleExecutionStatusWarningReason = typeof ruleExecutionStatusWarningReason[keyof typeof ruleExecutionStatusWarningReason]; +export type FilterStateStore = typeof filterStateStore[keyof typeof filterStateStore]; export type RuleParams = TypeOf; export type RuleSnoozeSchedule = TypeOf; diff --git a/x-pack/plugins/alerting/server/index.ts b/x-pack/plugins/alerting/server/index.ts index 200fe93931f86..b6962f65b4ab8 100644 --- a/x-pack/plugins/alerting/server/index.ts +++ b/x-pack/plugins/alerting/server/index.ts @@ -7,7 +7,6 @@ import type { PublicMethodsOf } from '@kbn/utility-types'; import { PluginConfigDescriptor, PluginInitializerContext } from '@kbn/core/server'; import { RulesClient as RulesClientClass } from './rules_client'; -import { AlertingPlugin } from './plugin'; import { configSchema } from './config'; import { AlertsConfigType } from './types'; @@ -70,7 +69,10 @@ export { } from './alerts_service'; export { getDataStreamAdapter } from './alerts_service/lib/data_stream_adapter'; -export const plugin = (initContext: PluginInitializerContext) => new AlertingPlugin(initContext); +export const plugin = async (initContext: PluginInitializerContext) => { + const { AlertingPlugin } = await import('./plugin'); + return new AlertingPlugin(initContext); +}; export const config: PluginConfigDescriptor = { schema: configSchema, diff --git a/x-pack/plugins/alerting/server/raw_rule_schema.ts b/x-pack/plugins/alerting/server/raw_rule_schema.ts index 65d4b48ec7d66..4072b15b19210 100644 --- a/x-pack/plugins/alerting/server/raw_rule_schema.ts +++ b/x-pack/plugins/alerting/server/raw_rule_schema.ts @@ -169,7 +169,7 @@ const rawRuleAlertsFilterSchema = schema.object({ params: schema.maybe(schema.recordOf(schema.string(), schema.any())), // better type? value: schema.maybe(schema.string()), }), - state$: schema.maybe( + $state: schema.maybe( schema.object({ store: schema.oneOf([schema.literal('appState'), schema.literal('globalState')]), }) diff --git a/x-pack/plugins/alerting/server/routes/lib/actions_schema.ts b/x-pack/plugins/alerting/server/routes/lib/actions_schema.ts index 9d6f89e070c3a..76661b2d33ff2 100644 --- a/x-pack/plugins/alerting/server/routes/lib/actions_schema.ts +++ b/x-pack/plugins/alerting/server/routes/lib/actions_schema.ts @@ -6,6 +6,7 @@ */ import { schema } from '@kbn/config-schema'; +import { FilterStateStore } from '@kbn/es-query'; import { validateTimezone } from './validate_timezone'; import { validateDurationSchema } from '../../lib'; import { validateHours } from './validate_hours'; @@ -36,7 +37,14 @@ export const actionsSchema = schema.arrayOf( schema.object({ query: schema.maybe(schema.recordOf(schema.string(), schema.any())), meta: schema.recordOf(schema.string(), schema.any()), - state$: schema.maybe(schema.object({ store: schema.string() })), + $state: schema.maybe( + schema.object({ + store: schema.oneOf([ + schema.literal(FilterStateStore.APP_STATE), + schema.literal(FilterStateStore.GLOBAL_STATE), + ]), + }) + ), }) ), dsl: schema.maybe(schema.string()), @@ -68,6 +76,7 @@ export const actionsSchema = schema.arrayOf( ), }) ), + use_alert_data_for_template: schema.maybe(schema.boolean()), }), { defaultValue: [] } ); diff --git a/x-pack/plugins/alerting/server/routes/lib/rewrite_actions.ts b/x-pack/plugins/alerting/server/routes/lib/rewrite_actions.ts index 2c2b0853d181b..16309485c18a1 100644 --- a/x-pack/plugins/alerting/server/routes/lib/rewrite_actions.ts +++ b/x-pack/plugins/alerting/server/routes/lib/rewrite_actions.ts @@ -15,20 +15,28 @@ export const rewriteActionsReq = ( ): NormalizedAlertAction[] => { if (!actions) return []; - return actions.map(({ frequency, alerts_filter: alertsFilter, ...action }) => { - return { - ...action, - ...(frequency - ? { - frequency: { - ...omit(frequency, 'notify_when'), - notifyWhen: frequency.notify_when, - }, - } - : {}), - ...(alertsFilter ? { alertsFilter } : {}), - }; - }); + return actions.map( + ({ + frequency, + alerts_filter: alertsFilter, + use_alert_data_for_template: useAlertDataForTemplate, + ...action + }) => { + return { + ...action, + useAlertDataForTemplate, + ...(frequency + ? { + frequency: { + ...omit(frequency, 'notify_when'), + notifyWhen: frequency.notify_when, + }, + } + : {}), + ...(alertsFilter ? { alertsFilter } : {}), + }; + } + ); }; export const rewriteActionsRes = (actions?: RuleAction[]) => { @@ -37,14 +45,17 @@ export const rewriteActionsRes = (actions?: RuleAction[]) => { notify_when: notifyWhen, }); if (!actions) return []; - return actions.map(({ actionTypeId, frequency, alertsFilter, ...action }) => ({ - ...action, - connector_type_id: actionTypeId, - ...(frequency ? { frequency: rewriteFrequency(frequency) } : {}), - ...(alertsFilter - ? { - alerts_filter: alertsFilter, - } - : {}), - })); + return actions.map( + ({ actionTypeId, frequency, alertsFilter, useAlertDataForTemplate, ...action }) => ({ + ...action, + connector_type_id: actionTypeId, + use_alert_data_for_template: useAlertDataForTemplate, + ...(frequency ? { frequency: rewriteFrequency(frequency) } : {}), + ...(alertsFilter + ? { + alerts_filter: alertsFilter, + } + : {}), + }) + ); }; diff --git a/x-pack/plugins/alerting/server/routes/rule/apis/bulk_edit/bulk_edit_rules_route.test.ts b/x-pack/plugins/alerting/server/routes/rule/apis/bulk_edit/bulk_edit_rules_route.test.ts index 1b1ed454c5207..9a77d46fb9208 100644 --- a/x-pack/plugins/alerting/server/routes/rule/apis/bulk_edit/bulk_edit_rules_route.test.ts +++ b/x-pack/plugins/alerting/server/routes/rule/apis/bulk_edit/bulk_edit_rules_route.test.ts @@ -114,6 +114,7 @@ describe('bulkEditRulesRoute', () => { foo: true, }, uuid: '123-456', + use_alert_data_for_template: false, }, ], }), diff --git a/x-pack/plugins/alerting/server/routes/rule/apis/create/create_rule_route.test.ts b/x-pack/plugins/alerting/server/routes/rule/apis/create/create_rule_route.test.ts index e952a72ec3859..a12b8ee5e177c 100644 --- a/x-pack/plugins/alerting/server/routes/rule/apis/create/create_rule_route.test.ts +++ b/x-pack/plugins/alerting/server/routes/rule/apis/create/create_rule_route.test.ts @@ -124,6 +124,7 @@ describe('createRuleRoute', () => { }, connector_type_id: 'test', uuid: '123-456', + use_alert_data_for_template: false, }, ], }; @@ -198,6 +199,7 @@ describe('createRuleRoute', () => { "params": Object { "foo": true, }, + "useAlertDataForTemplate": undefined, }, ], "alertTypeId": "1", @@ -314,6 +316,7 @@ describe('createRuleRoute', () => { "params": Object { "foo": true, }, + "useAlertDataForTemplate": undefined, }, ], "alertTypeId": "1", @@ -431,6 +434,7 @@ describe('createRuleRoute', () => { "params": Object { "foo": true, }, + "useAlertDataForTemplate": undefined, }, ], "alertTypeId": "1", @@ -548,6 +552,7 @@ describe('createRuleRoute', () => { "params": Object { "foo": true, }, + "useAlertDataForTemplate": undefined, }, ], "alertTypeId": "1", diff --git a/x-pack/plugins/alerting/server/routes/rule/apis/create/transforms/transform_create_body/v1.ts b/x-pack/plugins/alerting/server/routes/rule/apis/create/transforms/transform_create_body/v1.ts index c6b29f4577f4c..a9e9a25d05c95 100644 --- a/x-pack/plugins/alerting/server/routes/rule/apis/create/transforms/transform_create_body/v1.ts +++ b/x-pack/plugins/alerting/server/routes/rule/apis/create/transforms/transform_create_body/v1.ts @@ -15,25 +15,33 @@ import type { RuleParams } from '../../../../../../application/rule/types'; const transformCreateBodyActions = (actions: CreateRuleActionV1[]): CreateRuleData['actions'] => { if (!actions) return []; - return actions.map(({ frequency, alerts_filter: alertsFilter, ...action }) => { - return { - group: action.group, - id: action.id, - params: action.params, - actionTypeId: action.actionTypeId, - ...(action.uuid ? { uuid: action.uuid } : {}), - ...(frequency - ? { - frequency: { - summary: frequency.summary, - throttle: frequency.throttle, - notifyWhen: frequency.notify_when, - }, - } - : {}), - ...(alertsFilter ? { alertsFilter } : {}), - }; - }); + return actions.map( + ({ + frequency, + alerts_filter: alertsFilter, + use_alert_data_for_template: useAlertDataForTemplate, + ...action + }) => { + return { + group: action.group, + id: action.id, + params: action.params, + actionTypeId: action.actionTypeId, + useAlertDataForTemplate, + ...(action.uuid ? { uuid: action.uuid } : {}), + ...(frequency + ? { + frequency: { + summary: frequency.summary, + throttle: frequency.throttle, + notifyWhen: frequency.notify_when, + }, + } + : {}), + ...(alertsFilter ? { alertsFilter } : {}), + }; + } + ); }; export const transformCreateBody = ( diff --git a/x-pack/plugins/alerting/server/routes/rule/apis/resolve/resolve_rule_route.test.ts b/x-pack/plugins/alerting/server/routes/rule/apis/resolve/resolve_rule_route.test.ts index e83cd05b02edd..929dc6ad2ccc1 100644 --- a/x-pack/plugins/alerting/server/routes/rule/apis/resolve/resolve_rule_route.test.ts +++ b/x-pack/plugins/alerting/server/routes/rule/apis/resolve/resolve_rule_route.test.ts @@ -45,6 +45,7 @@ describe('resolveRuleRoute', () => { foo: true, }, uuid: '123-456', + useAlertDataForTemplate: false, }, ], consumer: 'bar', @@ -101,6 +102,7 @@ describe('resolveRuleRoute', () => { params: mockedRule.actions[0].params, connector_type_id: mockedRule.actions[0].actionTypeId, uuid: mockedRule.actions[0].uuid, + use_alert_data_for_template: mockedRule.actions[0].useAlertDataForTemplate, }, ], outcome: 'aliasMatch', diff --git a/x-pack/plugins/alerting/server/routes/rule/transforms/transform_rule_to_rule_response/v1.ts b/x-pack/plugins/alerting/server/routes/rule/transforms/transform_rule_to_rule_response/v1.ts index 74508cec9a640..3968e0e271620 100644 --- a/x-pack/plugins/alerting/server/routes/rule/transforms/transform_rule_to_rule_response/v1.ts +++ b/x-pack/plugins/alerting/server/routes/rule/transforms/transform_rule_to_rule_response/v1.ts @@ -49,11 +49,21 @@ export const transformRuleToRuleResponse = ( consumer: rule.consumer, schedule: rule.schedule, actions: rule.actions.map( - ({ group, id, actionTypeId, params, frequency, uuid, alertsFilter }) => ({ + ({ + group, + id, + actionTypeId, + params, + frequency, + uuid, + alertsFilter, + useAlertDataForTemplate, + }) => ({ group, id, params, connector_type_id: actionTypeId, + use_alert_data_for_template: useAlertDataForTemplate ?? false, ...(frequency ? { frequency: { diff --git a/x-pack/plugins/alerting/server/routes/update_rule.test.ts b/x-pack/plugins/alerting/server/routes/update_rule.test.ts index 5a4b3a19c0d7c..87901feab64cf 100644 --- a/x-pack/plugins/alerting/server/routes/update_rule.test.ts +++ b/x-pack/plugins/alerting/server/routes/update_rule.test.ts @@ -132,6 +132,7 @@ describe('updateRuleRoute', () => { "params": Object { "baz": true, }, + "useAlertDataForTemplate": undefined, "uuid": "1234-5678", }, ], diff --git a/x-pack/plugins/alerting/server/task_runner/execution_handler.ts b/x-pack/plugins/alerting/server/task_runner/execution_handler.ts index 288a4126c25a2..dd1caa21a240c 100644 --- a/x-pack/plugins/alerting/server/task_runner/execution_handler.ts +++ b/x-pack/plugins/alerting/server/task_runner/execution_handler.ts @@ -20,12 +20,16 @@ import { ActionsClient } from '@kbn/actions-plugin/server/actions_client'; import { chunk } from 'lodash'; import { GetSummarizedAlertsParams, IAlertsClient } from '../alerts_client/types'; import { AlertingEventLogger } from '../lib/alerting_event_logger/alerting_event_logger'; -import { parseDuration, CombinedSummarizedAlerts, ThrottledActions } from '../types'; +import { AlertHit, parseDuration, CombinedSummarizedAlerts, ThrottledActions } from '../types'; import { RuleRunMetricsStore } from '../lib/rule_run_metrics_store'; import { injectActionParams } from './inject_action_params'; import { Executable, ExecutionHandlerOptions, RuleTaskInstance } from './types'; import { TaskRunnerContext } from './task_runner_factory'; -import { transformActionParams, transformSummaryActionParams } from './transform_action_params'; +import { + transformActionParams, + TransformActionParamsOptions, + transformSummaryActionParams, +} from './transform_action_params'; import { Alert } from '../alert'; import { NormalizedRuleType } from '../rule_type_registry'; import { @@ -292,33 +296,40 @@ export class ExecutionHandler< }; } else { const ruleUrl = this.buildRuleUrl(spaceId); + const executableAlert = alert!; + const transformActionParamsOptions: TransformActionParamsOptions = { + actionsPlugin, + alertId: ruleId, + alertType: this.ruleType.id, + actionTypeId, + alertName: this.rule.name, + spaceId, + tags: this.rule.tags, + alertInstanceId: executableAlert.getId(), + alertUuid: executableAlert.getUuid(), + alertActionGroup: actionGroup, + alertActionGroupName: this.ruleTypeActionGroups!.get(actionGroup)!, + context: executableAlert.getContext(), + actionId: action.id, + state: executableAlert.getState(), + kibanaBaseUrl: this.taskRunnerContext.kibanaBaseUrl, + alertParams: this.rule.params, + actionParams: action.params, + flapping: executableAlert.getFlapping(), + ruleUrl: ruleUrl?.absoluteUrl, + }; + + if (executableAlert.isAlertAsData()) { + transformActionParamsOptions.aadAlert = executableAlert.getAlertAsData(); + } + const actionToRun = { ...action, params: injectActionParams({ actionTypeId, ruleUrl, ruleName: this.rule.name, - actionParams: transformActionParams({ - actionsPlugin, - alertId: ruleId, - alertType: this.ruleType.id, - actionTypeId, - alertName: this.rule.name, - spaceId, - tags: this.rule.tags, - alertInstanceId: alert.getId(), - alertUuid: alert.getUuid(), - alertActionGroup: actionGroup, - alertActionGroupName: this.ruleTypeActionGroups!.get(actionGroup)!, - context: alert.getContext(), - actionId: action.id, - state: alert.getState(), - kibanaBaseUrl: this.taskRunnerContext.kibanaBaseUrl, - alertParams: this.rule.params, - actionParams: action.params, - flapping: alert.getFlapping(), - ruleUrl: ruleUrl?.absoluteUrl, - }), + actionParams: transformActionParams(transformActionParamsOptions), }), }; @@ -570,7 +581,6 @@ export class ExecutionHandler< for (const action of this.rule.actions) { const alertsArray = Object.entries(alerts); let summarizedAlerts = null; - if (this.shouldGetSummarizedAlerts({ action, throttledSummaryActions })) { summarizedAlerts = await this.getSummarizedAlerts({ action, @@ -634,6 +644,15 @@ export class ExecutionHandler< continue; } + if (summarizedAlerts) { + const alertAsData = summarizedAlerts.all.data.find( + (alertHit: AlertHit) => alertHit._id === alert.getUuid() + ); + if (alertAsData) { + alert.setAlertAsData(alertAsData); + } + } + if (action.group === actionGroup && !this.isAlertMuted(alertId)) { if ( this.isRecoveredAlert(action.group) || @@ -667,12 +686,13 @@ export class ExecutionHandler< } return false; } - + if (action.useAlertDataForTemplate) { + return true; + } // we fetch summarizedAlerts to filter alerts in memory as well if (!isSummaryAction(action) && !action.alertsFilter) { return false; } - if ( isSummaryAction(action) && isSummaryActionThrottled({ diff --git a/x-pack/plugins/alerting/server/task_runner/fixtures.ts b/x-pack/plugins/alerting/server/task_runner/fixtures.ts index 163b9415c7e5d..490584e03c87f 100644 --- a/x-pack/plugins/alerting/server/task_runner/fixtures.ts +++ b/x-pack/plugins/alerting/server/task_runner/fixtures.ts @@ -355,7 +355,7 @@ export const generateRunnerResult = ({ alertInstances = {}, alertRecoveredInstances = {}, summaryActions = {}, - hasError = false, + taskRunError, }: GeneratorParams = {}) => { return { monitoring: { @@ -388,7 +388,7 @@ export const generateRunnerResult = ({ ...(state && { previousStartedAt: new Date('1970-01-01T00:00:00.000Z').toISOString() }), ...(state && { summaryActions }), }, - hasError, + taskRunError, }; }; diff --git a/x-pack/plugins/alerting/server/task_runner/task_runner.test.ts b/x-pack/plugins/alerting/server/task_runner/task_runner.test.ts index 03cf55f58606c..c066ac73f0ac0 100644 --- a/x-pack/plugins/alerting/server/task_runner/task_runner.test.ts +++ b/x-pack/plugins/alerting/server/task_runner/task_runner.test.ts @@ -1826,6 +1826,8 @@ describe('Task Runner', () => { }); test('recovers gracefully when the RuleType executor throws an exception', async () => { + const taskRunError = new Error(GENERIC_ERROR_MESSAGE); + ruleType.executor.mockImplementation( async ({ services: executorServices, @@ -1837,7 +1839,7 @@ describe('Task Runner', () => { string, RuleAlertData >) => { - throw new Error(GENERIC_ERROR_MESSAGE); + throw taskRunError; } ); @@ -1855,7 +1857,7 @@ describe('Task Runner', () => { const runnerResult = await taskRunner.run(); - expect(runnerResult).toEqual(generateRunnerResult({ successRatio: 0, hasError: true })); + expect(runnerResult).toEqual(generateRunnerResult({ successRatio: 0, taskRunError })); testAlertingEventLogCalls({ status: 'error', @@ -1877,9 +1879,11 @@ describe('Task Runner', () => { }); test('recovers gracefully when the Rule Task Runner throws an exception when loading rule to prepare for run', async () => { + const taskRunError = new Error(GENERIC_ERROR_MESSAGE); + // used in loadIndirectParams() which is called to load rule data rulesClient.getAlertFromRaw.mockImplementation(() => { - throw new Error(GENERIC_ERROR_MESSAGE); + throw taskRunError; }); const taskRunner = new TaskRunner({ @@ -1895,7 +1899,7 @@ describe('Task Runner', () => { const runnerResult = await taskRunner.run(); - expect(runnerResult).toEqual(generateRunnerResult({ successRatio: 0, hasError: true })); + expect(runnerResult).toEqual(generateRunnerResult({ successRatio: 0, taskRunError })); testAlertingEventLogCalls({ setRuleName: false, @@ -1908,8 +1912,10 @@ describe('Task Runner', () => { }); test('recovers gracefully when the Runner of a legacy Alert task which has no schedule throws an exception when fetching attributes', async () => { - rulesClient.get.mockImplementation(() => { - throw new Error(GENERIC_ERROR_MESSAGE); + const taskRunError = new TypeError(GENERIC_ERROR_MESSAGE); + + encryptedSavedObjectsClient.getDecryptedAsInternalUser.mockImplementation(() => { + throw taskRunError; }); // legacy alerts used to run by returning a new `runAt` instead of using a schedule @@ -1919,18 +1925,15 @@ describe('Task Runner', () => { const taskRunner = new TaskRunner({ ruleType, taskInstance: legacyTaskInstance, - context: taskRunnerFactoryInitializerParams, inMemoryMetrics, }); expect(AlertingEventLogger).toHaveBeenCalled(); - encryptedSavedObjectsClient.getDecryptedAsInternalUser.mockResolvedValueOnce(mockedRawRuleSO); - const runnerResult = await taskRunner.run(); expect(runnerResult).toEqual( - generateRunnerResult({ successRatio: 0, interval: '5m', hasError: true }) + generateRunnerResult({ successRatio: 0, interval: '5m', taskRunError }) ); expect(mockUsageCounter.incrementCounter).not.toHaveBeenCalled(); }); @@ -1977,10 +1980,6 @@ describe('Task Runner', () => { }); test('avoids rescheduling a failed Alert Task Runner when it throws due to failing to fetch the alert', async () => { - rulesClient.get.mockImplementation(() => { - throw SavedObjectsErrorHelpers.createGenericNotFoundError('alert', '1'); - }); - const taskRunner = new TaskRunner({ ruleType, taskInstance: { @@ -1990,7 +1989,6 @@ describe('Task Runner', () => { spaceId: 'foo', }, }, - context: taskRunnerFactoryInitializerParams, inMemoryMetrics, }); @@ -2021,10 +2019,6 @@ describe('Task Runner', () => { }); test('reschedules for next schedule interval if es connectivity error encountered and schedule interval is less than connectivity retry', async () => { - rulesClient.get.mockImplementation(() => { - throw SavedObjectsErrorHelpers.createGenericNotFoundEsUnavailableError('alert', '1'); - }); - const taskRunner = new TaskRunner({ ruleType, taskInstance: mockedTaskInstance, @@ -2067,10 +2061,6 @@ describe('Task Runner', () => { }); test('correctly logs warning when Alert Task Runner throws due to failing to fetch the alert in a space', async () => { - rulesClient.get.mockImplementation(() => { - throw SavedObjectsErrorHelpers.createGenericNotFoundError('alert', '1'); - }); - const taskRunner = new TaskRunner({ ruleType, taskInstance: { @@ -2607,6 +2597,7 @@ describe('Task Runner', () => { }); test('successfully stores failure runs', async () => { + const taskRunError = new Error(GENERIC_ERROR_MESSAGE); const taskRunner = new TaskRunner({ ruleType, taskInstance: mockedTaskInstance, @@ -2629,16 +2620,17 @@ describe('Task Runner', () => { string, RuleAlertData >) => { - throw new Error(GENERIC_ERROR_MESSAGE); + throw taskRunError; } ); const runnerResult = await taskRunner.run(); expect(runnerResult).toEqual( - generateRunnerResult({ successRatio: 0, success: false, hasError: true }) + generateRunnerResult({ successRatio: 0, success: false, taskRunError }) ); }); test('successfully stores the success ratio', async () => { + const taskRunError = new Error(GENERIC_ERROR_MESSAGE); const taskRunner = new TaskRunner({ ruleType, taskInstance: mockedTaskInstance, @@ -2665,7 +2657,7 @@ describe('Task Runner', () => { string, RuleAlertData >) => { - throw new Error(GENERIC_ERROR_MESSAGE); + throw taskRunError; } ); const runnerResult = await taskRunner.run(); @@ -2674,7 +2666,7 @@ describe('Task Runner', () => { generateRunnerResult({ successRatio: 0.75, history: [true, true, true, false], - hasError: true, + taskRunError, }) ); }); diff --git a/x-pack/plugins/alerting/server/task_runner/task_runner.ts b/x-pack/plugins/alerting/server/task_runner/task_runner.ts index 3cc9c2359c272..76d12d820fa23 100644 --- a/x-pack/plugins/alerting/server/task_runner/task_runner.ts +++ b/x-pack/plugins/alerting/server/task_runner/task_runner.ts @@ -10,7 +10,12 @@ import { omit, some } from 'lodash'; import { UsageCounter } from '@kbn/usage-collection-plugin/server'; import { v4 as uuidv4 } from 'uuid'; import { Logger } from '@kbn/core/server'; -import { ConcreteTaskInstance, throwUnrecoverableError } from '@kbn/task-manager-plugin/server'; +import { + ConcreteTaskInstance, + throwUnrecoverableError, + createTaskRunError, + TaskErrorSource, +} from '@kbn/task-manager-plugin/server'; import { nanosToMillis } from '@kbn/event-log-plugin/server'; import { DEFAULT_NAMESPACE_STRING } from '@kbn/core-saved-objects-utils-server'; import { ExecutionHandler, RunResult } from './execution_handler'; @@ -937,7 +942,9 @@ export class TaskRunner< return { interval: retryInterval }; }), monitoring: this.ruleMonitoring.getMonitoring(), - hasError: isErr(schedule), + ...(isErr(schedule) + ? { taskRunError: createTaskRunError(schedule.error, TaskErrorSource.FRAMEWORK) } + : {}), }; } diff --git a/x-pack/plugins/alerting/server/task_runner/transform_action_params.ts b/x-pack/plugins/alerting/server/task_runner/transform_action_params.ts index 7076e1fc7e35e..c9c55e07c3d75 100644 --- a/x-pack/plugins/alerting/server/task_runner/transform_action_params.ts +++ b/x-pack/plugins/alerting/server/task_runner/transform_action_params.ts @@ -6,6 +6,7 @@ */ import { PluginStartContract as ActionsPluginStartContract } from '@kbn/actions-plugin/server'; +import { AADAlert } from '@kbn/alerts-as-data-utils'; import { mapKeys, snakeCase } from 'lodash/fp'; import { RuleActionParams, @@ -15,7 +16,7 @@ import { SanitizedRule, } from '../types'; -interface TransformActionParamsOptions { +export interface TransformActionParamsOptions { actionsPlugin: ActionsPluginStartContract; alertId: string; alertType: string; @@ -35,6 +36,7 @@ interface TransformActionParamsOptions { context: AlertInstanceContext; ruleUrl?: string; flapping: boolean; + aadAlert?: AADAlert; } interface SummarizedAlertsWithAll { @@ -76,40 +78,45 @@ export function transformActionParams({ alertParams, ruleUrl, flapping, + aadAlert, }: TransformActionParamsOptions): RuleActionParams { // when the list of variables we pass in here changes, // the UI will need to be updated as well; see: // x-pack/plugins/triggers_actions_ui/public/application/lib/action_variables.ts - const variables = { - alertId, - alertName, - spaceId, - tags, - alertInstanceId, - alertActionGroup, - alertActionGroupName, - context, - date: new Date().toISOString(), - state, - kibanaBaseUrl, - params: alertParams, - rule: { - params: alertParams, - id: alertId, - name: alertName, - type: alertType, - spaceId, - tags, - url: ruleUrl, - }, - alert: { - id: alertInstanceId, - uuid: alertUuid, - actionGroup: alertActionGroup, - actionGroupName: alertActionGroupName, - flapping, - }, - }; + const variables = + aadAlert !== undefined + ? aadAlert + : { + alertId, + alertName, + spaceId, + tags, + alertInstanceId, + alertActionGroup, + alertActionGroupName, + context, + date: new Date().toISOString(), + state, + kibanaBaseUrl, + params: alertParams, + rule: { + params: alertParams, + id: alertId, + name: alertName, + type: alertType, + spaceId, + tags, + url: ruleUrl, + }, + alert: { + id: alertInstanceId, + uuid: alertUuid, + actionGroup: alertActionGroup, + actionGroupName: alertActionGroupName, + flapping, + }, + }; + return actionsPlugin.renderActionParameterTemplates( actionTypeId, actionId, diff --git a/x-pack/plugins/alerting/server/task_runner/types.ts b/x-pack/plugins/alerting/server/task_runner/types.ts index 157723bd22400..958ec20fe0136 100644 --- a/x-pack/plugins/alerting/server/task_runner/types.ts +++ b/x-pack/plugins/alerting/server/task_runner/types.ts @@ -6,7 +6,7 @@ */ import { KibanaRequest, Logger } from '@kbn/core/server'; -import { ConcreteTaskInstance } from '@kbn/task-manager-plugin/server'; +import { ConcreteTaskInstance, DecoratedError } from '@kbn/task-manager-plugin/server'; import { PublicMethodsOf } from '@kbn/utility-types'; import { ActionsClient } from '@kbn/actions-plugin/server/actions_client'; import { IAlertsClient } from '../alerts_client/types'; @@ -33,7 +33,7 @@ export interface RuleTaskRunResult { state: RuleTaskState; monitoring: RuleMonitoring | undefined; schedule: IntervalSchedule | undefined; - hasError: boolean; + taskRunError?: DecoratedError; } // This is the state of the alerting task after rule execution, which includes run metrics plus the task state diff --git a/x-pack/plugins/apm/server/index.ts b/x-pack/plugins/apm/server/index.ts index 1b8f8cb7c237e..5012526710a71 100644 --- a/x-pack/plugins/apm/server/index.ts +++ b/x-pack/plugins/apm/server/index.ts @@ -12,7 +12,6 @@ import { } from '@kbn/core/server'; import { maxSuggestions } from '@kbn/observability-plugin/common'; import { SearchAggregatedTransactionSetting } from '../common/aggregated_transactions'; -import { APMPlugin } from './plugin'; const disabledOnServerless = offeringBasedSchema({ serverless: schema.boolean({ @@ -125,8 +124,10 @@ export const config: PluginConfigDescriptor = { export type APMConfig = TypeOf; -export const plugin = (initContext: PluginInitializerContext) => - new APMPlugin(initContext); +export const plugin = async (initContext: PluginInitializerContext) => { + const { APMPlugin } = await import('./plugin'); + return new APMPlugin(initContext); +}; export { APM_SERVER_FEATURE_ID } from '../common/rules/apm_rule_types'; export { APMPlugin } from './plugin'; diff --git a/x-pack/plugins/apm/server/lib/helpers/create_es_client/create_internal_es_client/index.ts b/x-pack/plugins/apm/server/lib/helpers/create_es_client/create_internal_es_client/index.ts index e205a07129d3d..a6f31c8e279e2 100644 --- a/x-pack/plugins/apm/server/lib/helpers/create_es_client/create_internal_es_client/index.ts +++ b/x-pack/plugins/apm/server/lib/helpers/create_es_client/create_internal_es_client/index.ts @@ -8,7 +8,6 @@ import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { unwrapEsResponse } from '@kbn/observability-plugin/server'; import type { ESSearchResponse, ESSearchRequest } from '@kbn/es-types'; -import type { APMIndices } from '@kbn/apm-data-access-plugin/server'; import { ElasticsearchClient } from '@kbn/core-elasticsearch-server'; import { APMRouteHandlerResources } from '../../../../routes/apm_routes/register_apm_server_routes'; import { @@ -21,26 +20,20 @@ import { cancelEsRequestOnAbort } from '../cancel_es_request_on_abort'; export type APMIndexDocumentParams = estypes.IndexRequest; export type APMInternalESClient = Awaited< - ReturnType + ReturnType >; -export async function createInternalESClientWithContext({ - debug, - apmIndices, +export async function createInternalESClientWithResources({ + params, request, context, -}: { - debug: boolean; - apmIndices: APMIndices; - request: APMRouteHandlerResources['request']; - context: APMRouteHandlerResources['context']; -}) { +}: APMRouteHandlerResources) { const coreContext = await context.core; const { asInternalUser } = coreContext.elasticsearch.client; + const debug = params.query._inspect; return createInternalESClient({ debug, - apmIndices, request, elasticsearchClient: asInternalUser, }); @@ -48,12 +41,10 @@ export async function createInternalESClientWithContext({ export async function createInternalESClient({ debug, - apmIndices, request, elasticsearchClient, }: { debug: boolean; - apmIndices: APMIndices; request?: APMRouteHandlerResources['request']; elasticsearchClient: ElasticsearchClient; }) { @@ -92,7 +83,6 @@ export async function createInternalESClient({ } return { - apmIndices, search: async < TDocument = unknown, TSearchRequest extends ESSearchRequest = ESSearchRequest diff --git a/x-pack/plugins/apm/server/routes/fleet/create_cloud_apm_package_policy.ts b/x-pack/plugins/apm/server/routes/fleet/create_cloud_apm_package_policy.ts index a595c2f333a8d..457a4d4c4884e 100644 --- a/x-pack/plugins/apm/server/routes/fleet/create_cloud_apm_package_policy.ts +++ b/x-pack/plugins/apm/server/routes/fleet/create_cloud_apm_package_policy.ts @@ -12,6 +12,7 @@ import { KibanaRequest, } from '@kbn/core/server'; import { PackagePolicy } from '@kbn/fleet-plugin/common'; +import { APMIndices } from '@kbn/apm-data-access-plugin/server'; import { APM_SERVER_SCHEMA_SAVED_OBJECT_TYPE, APM_SERVER_SCHEMA_SAVED_OBJECT_ID, @@ -33,6 +34,7 @@ export async function createCloudApmPackgePolicy({ logger, internalESClient, request, + apmIndices, }: { cloudPluginSetup: APMPluginSetupDependencies['cloud']; fleetPluginStart: NonNullable; @@ -41,6 +43,7 @@ export async function createCloudApmPackgePolicy({ logger: Logger; internalESClient: APMInternalESClient; request: KibanaRequest; + apmIndices: APMIndices; }): Promise { const { attributes } = await savedObjectsClient.get( APM_SERVER_SCHEMA_SAVED_OBJECT_TYPE, @@ -61,6 +64,7 @@ export async function createCloudApmPackgePolicy({ internalESClient, packagePolicy: apmPackagePolicyDefinition, fleetPluginStart, + apmIndices, }); logger.info(`Fleet migration on Cloud - apmPackagePolicy create start`); const apmPackagePolicy = await fleetPluginStart.packagePolicyService.create( diff --git a/x-pack/plugins/apm/server/routes/fleet/merge_package_policy_with_apm.ts b/x-pack/plugins/apm/server/routes/fleet/merge_package_policy_with_apm.ts index 60fc87df078b9..ea6e1436f00d0 100644 --- a/x-pack/plugins/apm/server/routes/fleet/merge_package_policy_with_apm.ts +++ b/x-pack/plugins/apm/server/routes/fleet/merge_package_policy_with_apm.ts @@ -5,6 +5,7 @@ * 2.0. */ +import { APMIndices } from '@kbn/apm-data-access-plugin/server'; import { NewPackagePolicy } from '@kbn/fleet-plugin/common'; import { APMInternalESClient } from '../../lib/helpers/create_es_client/create_internal_es_client'; import { APMPluginStartDependencies } from '../../types'; @@ -19,13 +20,15 @@ export async function decoratePackagePolicyWithAgentConfigAndSourceMap({ packagePolicy, internalESClient, fleetPluginStart, + apmIndices, }: { packagePolicy: NewPackagePolicy; internalESClient: APMInternalESClient; fleetPluginStart: NonNullable; + apmIndices: APMIndices; }) { const [agentConfigurations, { artifacts }] = await Promise.all([ - listConfigurations(internalESClient), + listConfigurations(internalESClient, apmIndices), listSourceMapArtifacts({ fleetPluginStart }), ]); diff --git a/x-pack/plugins/apm/server/routes/fleet/register_fleet_policy_callbacks.ts b/x-pack/plugins/apm/server/routes/fleet/register_fleet_policy_callbacks.ts index 9008fabdd3e3b..1a6715cebff53 100644 --- a/x-pack/plugins/apm/server/routes/fleet/register_fleet_policy_callbacks.ts +++ b/x-pack/plugins/apm/server/routes/fleet/register_fleet_policy_callbacks.ts @@ -173,7 +173,6 @@ function onPackagePolicyCreateOrUpdate({ const internalESClient = await createInternalESClient({ debug: false, - apmIndices, elasticsearchClient: asInternalUser, }); @@ -181,6 +180,7 @@ function onPackagePolicyCreateOrUpdate({ internalESClient, fleetPluginStart, packagePolicy, + apmIndices, }); }; } diff --git a/x-pack/plugins/apm/server/routes/fleet/route.ts b/x-pack/plugins/apm/server/routes/fleet/route.ts index 3223d71a77b49..3807a87b9ec7c 100644 --- a/x-pack/plugins/apm/server/routes/fleet/route.ts +++ b/x-pack/plugins/apm/server/routes/fleet/route.ts @@ -14,7 +14,7 @@ import { APM_SERVER_SCHEMA_SAVED_OBJECT_TYPE, } from '../../../common/apm_saved_object_constants'; import { ApmFeatureFlags } from '../../../common/apm_feature_flags'; -import { createInternalESClientWithContext } from '../../lib/helpers/create_es_client/create_internal_es_client'; +import { createInternalESClientWithResources } from '../../lib/helpers/create_es_client/create_internal_es_client'; import { getInternalSavedObjectsClient } from '../../lib/helpers/get_internal_saved_objects_client'; import { createApmServerRoute } from '../apm_routes/create_apm_server_route'; import { createCloudApmPackgePolicy } from './create_cloud_apm_package_policy'; @@ -172,13 +172,9 @@ const createCloudApmPackagePolicyRoute = createApmServerRoute({ throw Boom.forbidden(CLOUD_SUPERUSER_REQUIRED_MESSAGE); } - const internalESClient = await createInternalESClientWithContext({ - context, - request, - debug: resources.params.query._inspect, - apmIndices, - }); - + const internalESClient = await createInternalESClientWithResources( + resources + ); const cloudApmPackagePolicy = await createCloudApmPackgePolicy({ cloudPluginSetup, fleetPluginStart, @@ -186,6 +182,7 @@ const createCloudApmPackagePolicyRoute = createApmServerRoute({ esClient, logger, internalESClient, + apmIndices, request, }); diff --git a/x-pack/plugins/apm/server/routes/fleet/sync_agent_configs_to_apm_package_policies.ts b/x-pack/plugins/apm/server/routes/fleet/sync_agent_configs_to_apm_package_policies.ts index 3eb7308e7908f..ce8d4421dfc46 100644 --- a/x-pack/plugins/apm/server/routes/fleet/sync_agent_configs_to_apm_package_policies.ts +++ b/x-pack/plugins/apm/server/routes/fleet/sync_agent_configs_to_apm_package_policies.ts @@ -6,6 +6,7 @@ */ import { CoreStart, SavedObjectsClientContract } from '@kbn/core/server'; +import { APMIndices } from '@kbn/apm-data-access-plugin/server'; import { TelemetryUsageCounter } from '../typings'; import { APMPluginStartDependencies } from '../../types'; import { getInternalSavedObjectsClient } from '../../lib/helpers/get_internal_saved_objects_client'; @@ -18,11 +19,13 @@ export async function syncAgentConfigsToApmPackagePolicies({ coreStartPromise, fleetPluginStart, internalESClient, + apmIndices, telemetryUsageCounter, }: { coreStartPromise: Promise; fleetPluginStart: NonNullable; internalESClient: APMInternalESClient; + apmIndices: APMIndices; telemetryUsageCounter?: TelemetryUsageCounter; }) { if (telemetryUsageCounter) { @@ -36,7 +39,7 @@ export async function syncAgentConfigsToApmPackagePolicies({ const [savedObjectsClient, agentConfigurations, packagePolicies] = await Promise.all([ getInternalSavedObjectsClient(coreStart), - listConfigurations(internalESClient), + listConfigurations(internalESClient, apmIndices), getApmPackagePolicies({ coreStart, fleetPluginStart }), ]); diff --git a/x-pack/plugins/apm/server/routes/settings/agent_configuration/find_exact_configuration.ts b/x-pack/plugins/apm/server/routes/settings/agent_configuration/find_exact_configuration.ts index 3cd71c1d29027..232c3d2d50c46 100644 --- a/x-pack/plugins/apm/server/routes/settings/agent_configuration/find_exact_configuration.ts +++ b/x-pack/plugins/apm/server/routes/settings/agent_configuration/find_exact_configuration.ts @@ -6,6 +6,7 @@ */ import type { SearchHit } from '@kbn/es-types'; +import { APMIndices } from '@kbn/apm-data-access-plugin/server'; import { AgentConfiguration } from '../../../../common/agent_configuration/configuration_types'; import { SERVICE_ENVIRONMENT, @@ -19,9 +20,11 @@ import { getConfigsAppliedToAgentsThroughFleet } from './get_config_applied_to_a export async function findExactConfiguration({ service, internalESClient, + apmIndices, }: { service: AgentConfiguration['service']; internalESClient: APMInternalESClient; + apmIndices: APMIndices; }) { const serviceNameFilter = service.name ? { term: { [SERVICE_NAME]: service.name } } @@ -45,7 +48,7 @@ export async function findExactConfiguration({ 'find_exact_agent_configuration', params ), - getConfigsAppliedToAgentsThroughFleet(internalESClient), + getConfigsAppliedToAgentsThroughFleet(internalESClient, apmIndices), ]); const hit = agentConfig.hits.hits[0] as diff --git a/x-pack/plugins/apm/server/routes/settings/agent_configuration/get_config_applied_to_agent_through_fleet.ts b/x-pack/plugins/apm/server/routes/settings/agent_configuration/get_config_applied_to_agent_through_fleet.ts index 7d4382e054783..067d7565247b9 100644 --- a/x-pack/plugins/apm/server/routes/settings/agent_configuration/get_config_applied_to_agent_through_fleet.ts +++ b/x-pack/plugins/apm/server/routes/settings/agent_configuration/get_config_applied_to_agent_through_fleet.ts @@ -7,14 +7,17 @@ import { termQuery, rangeQuery } from '@kbn/observability-plugin/server'; import datemath from '@kbn/datemath'; +import { APMIndices } from '@kbn/apm-data-access-plugin/server'; import { METRICSET_NAME } from '../../../../common/es_fields/apm'; import { APMInternalESClient } from '../../../lib/helpers/create_es_client/create_internal_es_client'; export async function getConfigsAppliedToAgentsThroughFleet( - internalESClient: APMInternalESClient + internalESClient: APMInternalESClient, + apmIndices: APMIndices ) { const params = { - index: internalESClient.apmIndices.metric, + index: apmIndices.metric, + track_total_hits: 0, size: 0, body: { query: { diff --git a/x-pack/plugins/apm/server/routes/settings/agent_configuration/list_configurations.ts b/x-pack/plugins/apm/server/routes/settings/agent_configuration/list_configurations.ts index 1cca702dfb45f..940ac7cd0b5a5 100644 --- a/x-pack/plugins/apm/server/routes/settings/agent_configuration/list_configurations.ts +++ b/x-pack/plugins/apm/server/routes/settings/agent_configuration/list_configurations.ts @@ -5,6 +5,7 @@ * 2.0. */ +import { APMIndices } from '@kbn/apm-data-access-plugin/server'; import { AgentConfiguration } from '../../../../common/agent_configuration/configuration_types'; import { convertConfigSettingsToString } from './convert_settings_to_string'; import { getConfigsAppliedToAgentsThroughFleet } from './get_config_applied_to_agent_through_fleet'; @@ -12,7 +13,8 @@ import { APMInternalESClient } from '../../../lib/helpers/create_es_client/creat import { APM_AGENT_CONFIGURATION_INDEX } from '../apm_indices/apm_system_index_constants'; export async function listConfigurations( - internalESClient: APMInternalESClient + internalESClient: APMInternalESClient, + apmIndices: APMIndices ) { const params = { index: APM_AGENT_CONFIGURATION_INDEX, @@ -24,7 +26,7 @@ export async function listConfigurations( 'list_agent_configuration', params ), - getConfigsAppliedToAgentsThroughFleet(internalESClient), + getConfigsAppliedToAgentsThroughFleet(internalESClient, apmIndices), ]); return agentConfigs.hits.hits diff --git a/x-pack/plugins/apm/server/routes/settings/agent_configuration/queries.test.ts b/x-pack/plugins/apm/server/routes/settings/agent_configuration/queries.test.ts index 4d2fb4f768ec6..5a26721150660 100644 --- a/x-pack/plugins/apm/server/routes/settings/agent_configuration/queries.test.ts +++ b/x-pack/plugins/apm/server/routes/settings/agent_configuration/queries.test.ts @@ -53,8 +53,9 @@ describe('agent configuration queries', () => { describe('listConfigurations', () => { it('fetches configurations', async () => { - mock = await inspectSearchParams(({ mockInternalESClient }) => - listConfigurations(mockInternalESClient) + mock = await inspectSearchParams( + ({ mockInternalESClient, mockIndices }) => + listConfigurations(mockInternalESClient, mockIndices) ); expect(mock.params).toMatchSnapshot(); @@ -92,33 +93,39 @@ describe('agent configuration queries', () => { describe('findExactConfiguration', () => { it('find configuration by service.name', async () => { - mock = await inspectSearchParams(({ mockInternalESClient }) => - findExactConfiguration({ - service: { name: 'foo' }, - internalESClient: mockInternalESClient, - }) + mock = await inspectSearchParams( + ({ mockInternalESClient, mockIndices }) => + findExactConfiguration({ + service: { name: 'foo' }, + internalESClient: mockInternalESClient, + apmIndices: mockIndices, + }) ); expect(mock.params).toMatchSnapshot(); }); it('find configuration by service.environment', async () => { - mock = await inspectSearchParams(({ mockInternalESClient }) => - findExactConfiguration({ - service: { environment: 'bar' }, - internalESClient: mockInternalESClient, - }) + mock = await inspectSearchParams( + ({ mockInternalESClient, mockIndices }) => + findExactConfiguration({ + service: { environment: 'bar' }, + internalESClient: mockInternalESClient, + apmIndices: mockIndices, + }) ); expect(mock.params).toMatchSnapshot(); }); it('find configuration by service.name and service.environment', async () => { - mock = await inspectSearchParams(({ mockInternalESClient }) => - findExactConfiguration({ - service: { name: 'foo', environment: 'bar' }, - internalESClient: mockInternalESClient, - }) + mock = await inspectSearchParams( + ({ mockInternalESClient, mockIndices }) => + findExactConfiguration({ + service: { name: 'foo', environment: 'bar' }, + internalESClient: mockInternalESClient, + apmIndices: mockIndices, + }) ); expect(mock.params).toMatchSnapshot(); diff --git a/x-pack/plugins/apm/server/routes/settings/agent_configuration/route.ts b/x-pack/plugins/apm/server/routes/settings/agent_configuration/route.ts index c11eba5ac7740..b2c06044838ff 100644 --- a/x-pack/plugins/apm/server/routes/settings/agent_configuration/route.ts +++ b/x-pack/plugins/apm/server/routes/settings/agent_configuration/route.ts @@ -26,7 +26,7 @@ import { import { getSearchTransactionsEvents } from '../../../lib/helpers/transactions'; import { syncAgentConfigsToApmPackagePolicies } from '../../fleet/sync_agent_configs_to_apm_package_policies'; import { getApmEventClient } from '../../../lib/helpers/get_apm_event_client'; -import { createInternalESClientWithContext } from '../../../lib/helpers/create_es_client/create_internal_es_client'; +import { createInternalESClientWithResources } from '../../../lib/helpers/create_es_client/create_internal_es_client'; import { AgentConfiguration } from '../../../../common/agent_configuration/configuration_types'; import { ApmFeatureFlags } from '../../../../common/apm_feature_flags'; @@ -49,17 +49,14 @@ const agentConfigurationRoute = createApmServerRoute({ }> => { throwNotFoundIfAgentConfigNotAvailable(resources.featureFlags); - const { context, request, params } = resources; const apmIndices = await resources.getApmIndices(); - - const internalESClient = await createInternalESClientWithContext({ - context, - request, - debug: params.query._inspect, - apmIndices, - }); - - const configurations = await listConfigurations(internalESClient); + const internalESClient = await createInternalESClientWithResources( + resources + ); + const configurations = await listConfigurations( + internalESClient, + apmIndices + ); return { configurations }; }, @@ -75,20 +72,17 @@ const getSingleAgentConfigurationRoute = createApmServerRoute({ handler: async (resources): Promise => { throwNotFoundIfAgentConfigNotAvailable(resources.featureFlags); - const { params, logger, context, request } = resources; - const { name, environment, _inspect } = params.query; + const { params, logger } = resources; + const { name, environment } = params.query; const service = { name, environment }; const apmIndices = await resources.getApmIndices(); - - const internalESClient = await createInternalESClientWithContext({ - context, - request, - debug: _inspect, - apmIndices, - }); + const internalESClient = await createInternalESClientWithResources( + resources + ); const exactConfig = await findExactConfiguration({ service, internalESClient, + apmIndices, }); if (!exactConfig) { @@ -117,20 +111,16 @@ const deleteAgentConfigurationRoute = createApmServerRoute({ handler: async (resources): Promise<{ result: string }> => { throwNotFoundIfAgentConfigNotAvailable(resources.featureFlags); - const { params, logger, core, telemetryUsageCounter, context, request } = - resources; + const { params, logger, core, telemetryUsageCounter } = resources; const { service } = params.body; const apmIndices = await resources.getApmIndices(); - - const internalESClient = await createInternalESClientWithContext({ - context, - request, - debug: params.query._inspect, - apmIndices, - }); + const internalESClient = await createInternalESClientWithResources( + resources + ); const exactConfig = await findExactConfiguration({ service, internalESClient, + apmIndices, }); if (!exactConfig) { logger.info( @@ -154,6 +144,7 @@ const deleteAgentConfigurationRoute = createApmServerRoute({ coreStartPromise: core.start(), fleetPluginStart: await resources.plugins.fleet.start(), internalESClient, + apmIndices, telemetryUsageCounter, }); logger.info( @@ -177,23 +168,19 @@ const createOrUpdateAgentConfigurationRoute = createApmServerRoute({ ]), handler: async (resources): Promise => { throwNotFoundIfAgentConfigNotAvailable(resources.featureFlags); - const { params, logger, core, telemetryUsageCounter, context, request } = - resources; + const { params, logger, core, telemetryUsageCounter } = resources; const { body, query } = params; const apmIndices = await resources.getApmIndices(); - - const internalESClient = await createInternalESClientWithContext({ - context, - request, - debug: params.query._inspect, - apmIndices, - }); + const internalESClient = await createInternalESClientWithResources( + resources + ); // if the config already exists, it is fetched and updated // this is to avoid creating two configs with identical service params const exactConfig = await findExactConfiguration({ service: body.service, internalESClient, + apmIndices, }); // if the config exists ?overwrite=true is required @@ -219,6 +206,7 @@ const createOrUpdateAgentConfigurationRoute = createApmServerRoute({ await syncAgentConfigsToApmPackagePolicies({ coreStartPromise: core.start(), fleetPluginStart: await resources.plugins.fleet.start(), + apmIndices, internalESClient, telemetryUsageCounter, }); @@ -248,21 +236,17 @@ const agentConfigurationSearchRoute = createApmServerRoute({ ): Promise | null> => { throwNotFoundIfAgentConfigNotAvailable(resources.featureFlags); - const { params, logger, context, request } = resources; + const { params, logger } = resources; const { service, etag, mark_as_applied_by_agent: markAsAppliedByAgent, } = params.body; - const apmIndices = await resources.getApmIndices(); - const internalESClient = await createInternalESClientWithContext({ - context, - request, - debug: params.query._inspect, - apmIndices, - }); + const internalESClient = await createInternalESClientWithResources( + resources + ); const configuration = await searchConfigurations({ service, internalESClient, @@ -322,16 +306,9 @@ const listAgentConfigurationEnvironmentsRoute = createApmServerRoute({ }> => { throwNotFoundIfAgentConfigNotAvailable(resources.featureFlags); - const { context, request, params, config } = resources; - const apmIndices = await resources.getApmIndices(); - + const { context, params, config } = resources; const [internalESClient, apmEventClient] = await Promise.all([ - createInternalESClientWithContext({ - context, - request, - debug: params.query._inspect, - apmIndices, - }), + createInternalESClientWithResources(resources), getApmEventClient(resources), ]); const coreContext = await context.core; diff --git a/x-pack/plugins/apm/server/routes/settings/custom_link/route.ts b/x-pack/plugins/apm/server/routes/settings/custom_link/route.ts index 1db1d74fb7134..752c7efb8cbe2 100644 --- a/x-pack/plugins/apm/server/routes/settings/custom_link/route.ts +++ b/x-pack/plugins/apm/server/routes/settings/custom_link/route.ts @@ -19,7 +19,7 @@ import { getTransaction } from './get_transaction'; import { listCustomLinks } from './list_custom_links'; import { createApmServerRoute } from '../../apm_routes/create_apm_server_route'; import { getApmEventClient } from '../../../lib/helpers/get_apm_event_client'; -import { createInternalESClientWithContext } from '../../../lib/helpers/create_es_client/create_internal_es_client'; +import { createInternalESClientWithResources } from '../../../lib/helpers/create_es_client/create_internal_es_client'; import { Transaction } from '../../../../typings/es_schemas/ui/transaction'; import { CustomLink } from '../../../../common/custom_link/custom_link_types'; @@ -50,22 +50,17 @@ const listCustomLinksRoute = createApmServerRoute({ ): Promise<{ customLinks: CustomLink[]; }> => { - const { context, params, request } = resources; + const { context, params } = resources; const licensingContext = await context.licensing; - const apmIndices = await resources.getApmIndices(); if (!isActiveGoldLicense(licensingContext.license)) { throw Boom.forbidden(INVALID_LICENSE); } const { query } = params; - - const internalESClient = await createInternalESClientWithContext({ - context, - request, - debug: resources.params.query._inspect, - apmIndices, - }); + const internalESClient = await createInternalESClientWithResources( + resources + ); // picks only the items listed in FILTER_OPTIONS const filters = pick(query, FILTER_OPTIONS); @@ -84,20 +79,16 @@ const createCustomLinkRoute = createApmServerRoute({ }), options: { tags: ['access:apm', 'access:apm_write'] }, handler: async (resources): Promise => { - const { context, params, request } = resources; + const { context, params } = resources; const licensingContext = await context.licensing; - const apmIndices = await resources.getApmIndices(); if (!isActiveGoldLicense(licensingContext.license)) { throw Boom.forbidden(INVALID_LICENSE); } - const internalESClient = await createInternalESClientWithContext({ - context, - request, - debug: resources.params.query._inspect, - apmIndices, - }); + const internalESClient = await createInternalESClientWithResources( + resources + ); const customLink = params.body; notifyFeatureUsage({ @@ -121,20 +112,16 @@ const updateCustomLinkRoute = createApmServerRoute({ tags: ['access:apm', 'access:apm_write'], }, handler: async (resources): Promise => { - const { params, context, request } = resources; + const { params, context } = resources; const licensingContext = await context.licensing; - const apmIndices = await resources.getApmIndices(); if (!isActiveGoldLicense(licensingContext.license)) { throw Boom.forbidden(INVALID_LICENSE); } - const internalESClient = await createInternalESClientWithContext({ - context, - request, - debug: resources.params.query._inspect, - apmIndices, - }); + const internalESClient = await createInternalESClientWithResources( + resources + ); const { id } = params.path; const customLink = params.body; @@ -158,26 +145,18 @@ const deleteCustomLinkRoute = createApmServerRoute({ tags: ['access:apm', 'access:apm_write'], }, handler: async (resources): Promise<{ result: string }> => { - const { context, params, request } = resources; + const { context, params } = resources; const licensingContext = await context.licensing; - const apmIndices = await resources.getApmIndices(); if (!isActiveGoldLicense(licensingContext.license)) { throw Boom.forbidden(INVALID_LICENSE); } - const internalESClient = await createInternalESClientWithContext({ - context, - request, - debug: resources.params.query._inspect, - apmIndices, - }); + const internalESClient = await createInternalESClientWithResources( + resources + ); const { id } = params.path; - const res = await deleteCustomLink({ - customLinkId: id, - internalESClient, - }); - return res; + return deleteCustomLink({ customLinkId: id, internalESClient }); }, }); diff --git a/x-pack/plugins/apm_data_access/server/index.ts b/x-pack/plugins/apm_data_access/server/index.ts index 4ef9a47937733..f322ff2eb910d 100644 --- a/x-pack/plugins/apm_data_access/server/index.ts +++ b/x-pack/plugins/apm_data_access/server/index.ts @@ -7,7 +7,6 @@ import { schema, TypeOf } from '@kbn/config-schema'; import { PluginConfigDescriptor, PluginInitializerContext } from '@kbn/core/server'; -import { ApmDataAccessPlugin } from './plugin'; const configSchema = schema.object({ indices: schema.object({ @@ -78,7 +77,8 @@ export const config: PluginConfigDescriptor = { export type APMDataAccessConfig = TypeOf; export type APMIndices = APMDataAccessConfig['indices']; -export function plugin(initializerContext: PluginInitializerContext) { +export async function plugin(initializerContext: PluginInitializerContext) { + const { ApmDataAccessPlugin } = await import('./plugin'); return new ApmDataAccessPlugin(initializerContext); } diff --git a/x-pack/plugins/asset_manager/server/index.ts b/x-pack/plugins/asset_manager/server/index.ts index 5dbecbee5f9da..86e5e855a74c9 100644 --- a/x-pack/plugins/asset_manager/server/index.ts +++ b/x-pack/plugins/asset_manager/server/index.ts @@ -7,12 +7,7 @@ import { PluginInitializerContext } from '@kbn/core-plugins-server'; import { AssetManagerConfig } from '../common/config'; -import { - AssetManagerServerPlugin, - AssetManagerServerPluginSetup, - AssetManagerServerPluginStart, - config, -} from './plugin'; +import { AssetManagerServerPluginSetup, AssetManagerServerPluginStart, config } from './plugin'; import type { WriteSamplesPostBody } from './routes/sample_assets'; export type { @@ -23,5 +18,7 @@ export type { }; export { config }; -export const plugin = (context: PluginInitializerContext) => - new AssetManagerServerPlugin(context); +export const plugin = async (context: PluginInitializerContext) => { + const { AssetManagerServerPlugin } = await import('./plugin'); + return new AssetManagerServerPlugin(context); +}; diff --git a/x-pack/plugins/banners/server/index.ts b/x-pack/plugins/banners/server/index.ts index 053de8b5c12b2..4b029ad07743b 100644 --- a/x-pack/plugins/banners/server/index.ts +++ b/x-pack/plugins/banners/server/index.ts @@ -6,7 +6,9 @@ */ import { PluginInitializer } from '@kbn/core/server'; -import { BannersPlugin } from './plugin'; export { config } from './config'; -export const plugin: PluginInitializer<{}, {}, {}, {}> = (context) => new BannersPlugin(context); +export const plugin: PluginInitializer<{}, {}, {}, {}> = async (context) => { + const { BannersPlugin } = await import('./plugin'); + return new BannersPlugin(context); +}; diff --git a/x-pack/plugins/canvas/public/components/workpad_header/share_menu/utils.ts b/x-pack/plugins/canvas/public/components/workpad_header/share_menu/utils.ts index 63477a325824b..d535d7dceaf0b 100644 --- a/x-pack/plugins/canvas/public/components/workpad_header/share_menu/utils.ts +++ b/x-pack/plugins/canvas/public/components/workpad_header/share_menu/utils.ts @@ -5,8 +5,8 @@ * 2.0. */ -import { JobAppParamsPDFV2 } from '@kbn/reporting-plugin/common/types'; import type { RedirectOptions } from '@kbn/share-plugin/public'; +import { JobAppParamsPDFV2 } from '@kbn/reporting-export-types-pdf-common'; import { CanvasAppLocatorParams, CANVAS_APP_LOCATOR } from '../../../../common/locator'; import { CanvasWorkpad } from '../../../../types'; diff --git a/x-pack/plugins/canvas/server/feature.test.ts b/x-pack/plugins/canvas/server/feature.test.ts index 513db3f668e14..b4a891af13c6f 100644 --- a/x-pack/plugins/canvas/server/feature.test.ts +++ b/x-pack/plugins/canvas/server/feature.test.ts @@ -6,8 +6,8 @@ */ import { getCanvasFeature } from './feature'; -import { ReportingStart } from '@kbn/reporting-plugin/server/types'; import { reportingMock } from '@kbn/reporting-plugin/server/mocks'; +import { ReportingStart } from '@kbn/reporting-plugin/server/types'; let mockReportingPlugin: ReportingStart; beforeEach(() => { diff --git a/x-pack/plugins/canvas/server/feature.ts b/x-pack/plugins/canvas/server/feature.ts index f5fc320fbeb50..01ae5249629e9 100644 --- a/x-pack/plugins/canvas/server/feature.ts +++ b/x-pack/plugins/canvas/server/feature.ts @@ -8,13 +8,13 @@ import { i18n } from '@kbn/i18n'; import { DEFAULT_APP_CATEGORIES } from '@kbn/core/server'; import { KibanaFeatureConfig } from '@kbn/features-plugin/common'; -import { ReportingSetup } from '@kbn/reporting-plugin/server'; +import { ReportingStart } from '@kbn/reporting-plugin/server/types'; /* * Register Canvas as a Kibana feature, * with Reporting sub-feature integration (if enabled) */ -export function getCanvasFeature(plugins: { reporting?: ReportingSetup }): KibanaFeatureConfig { +export function getCanvasFeature(plugins: { reporting?: ReportingStart }): KibanaFeatureConfig { const includeReporting = plugins.reporting && plugins.reporting.usesUiCapabilities(); return { diff --git a/x-pack/plugins/canvas/server/index.ts b/x-pack/plugins/canvas/server/index.ts index 74c5810481e00..c72530f911cc1 100644 --- a/x-pack/plugins/canvas/server/index.ts +++ b/x-pack/plugins/canvas/server/index.ts @@ -6,12 +6,13 @@ */ import { PluginConfigDescriptor, PluginInitializerContext } from '@kbn/core/server'; -import { CanvasPlugin } from './plugin'; import { ConfigSchema } from './config'; export const config: PluginConfigDescriptor = { schema: ConfigSchema, }; -export const plugin = (initializerContext: PluginInitializerContext) => - new CanvasPlugin(initializerContext); +export const plugin = async (initializerContext: PluginInitializerContext) => { + const { CanvasPlugin } = await import('./plugin'); + return new CanvasPlugin(initializerContext); +}; diff --git a/x-pack/plugins/canvas/server/plugin.ts b/x-pack/plugins/canvas/server/plugin.ts index 8c9748cc47887..9dd6dc1bdd64f 100644 --- a/x-pack/plugins/canvas/server/plugin.ts +++ b/x-pack/plugins/canvas/server/plugin.ts @@ -15,8 +15,8 @@ import { BfetchServerSetup } from '@kbn/bfetch-plugin/server'; import { UsageCollectionSetup } from '@kbn/usage-collection-plugin/server'; import { HomeServerPluginSetup } from '@kbn/home-plugin/server'; import { EmbeddableSetup } from '@kbn/embeddable-plugin/server'; -import { ReportingSetup } from '@kbn/reporting-plugin/server'; import { PluginSetupContract as FeaturesPluginSetup } from '@kbn/features-plugin/server'; +import { ReportingServerPluginSetup } from '@kbn/reporting-server'; import { getCanvasFeature } from './feature'; import { initRoutes } from './routes'; import { registerCanvasUsageCollector } from './collectors'; @@ -35,7 +35,7 @@ interface PluginsSetup { home: HomeServerPluginSetup; bfetch: BfetchServerSetup; data: DataPluginSetup; - reporting?: ReportingSetup; + reporting?: ReportingServerPluginSetup; usageCollection?: UsageCollectionSetup; } diff --git a/x-pack/plugins/canvas/tsconfig.json b/x-pack/plugins/canvas/tsconfig.json index 45b22e422dc6e..b3a9ef19723e3 100644 --- a/x-pack/plugins/canvas/tsconfig.json +++ b/x-pack/plugins/canvas/tsconfig.json @@ -84,6 +84,8 @@ "@kbn/content-management-plugin", "@kbn/react-kibana-context-theme", "@kbn/shared-ux-page-kibana-template", + "@kbn/reporting-server", + "@kbn/reporting-export-types-pdf-common", ], "exclude": [ "target/**/*", diff --git a/x-pack/plugins/cases/common/constants/index.ts b/x-pack/plugins/cases/common/constants/index.ts index f2c2dcef9bb2e..5a540b610135c 100644 --- a/x-pack/plugins/cases/common/constants/index.ts +++ b/x-pack/plugins/cases/common/constants/index.ts @@ -202,6 +202,7 @@ export const SEARCH_DEBOUNCE_MS = 500; export const LOCAL_STORAGE_KEYS = { casesQueryParams: 'cases.list.queryParams', casesFilterOptions: 'cases.list.filterOptions', + casesTableColumns: 'cases.list.tableColumns', }; /** diff --git a/x-pack/plugins/cases/common/types/api/case/v1.test.ts b/x-pack/plugins/cases/common/types/api/case/v1.test.ts index e6e7286ed4766..a509bdee36525 100644 --- a/x-pack/plugins/cases/common/types/api/case/v1.test.ts +++ b/x-pack/plugins/cases/common/types/api/case/v1.test.ts @@ -40,6 +40,7 @@ import { CasesFindRequestSortFieldsRt, CasesFindResponseRt, CasesPatchRequestRt, + CasesSearchRequestRt, } from './v1'; import { CustomFieldTypes } from '../../domain/custom_field/v1'; @@ -461,6 +462,50 @@ describe('CasesFindRequestRt', () => { }); }); +describe('CasesSearchRequestRt', () => { + const defaultRequest = { + tags: ['new', 'case'], + status: CaseStatuses.open, + severity: CaseSeverity.LOW, + assignees: ['damaged_racoon'], + reporters: ['damaged_racoon'], + defaultSearchOperator: 'AND', + from: 'now', + page: '1', + perPage: '10', + search: 'search text', + searchFields: ['title', 'description'], + to: '1w', + sortOrder: 'desc', + sortField: 'createdAt', + owner: 'cases', + customFields: { + toggle_custom_field_key: [true], + another_custom_field: [null, false], + text_custom_field: ['hello'], + number_custom_field: [1234], + }, + }; + + it('has expected attributes in request', () => { + const query = CasesSearchRequestRt.decode(defaultRequest); + + expect(query).toStrictEqual({ + _tag: 'Right', + right: { ...defaultRequest, page: 1, perPage: 10 }, + }); + }); + + it('removes foo:bar attributes from request', () => { + const query = CasesSearchRequestRt.decode({ ...defaultRequest, foo: 'bar' }); + + expect(query).toStrictEqual({ + _tag: 'Right', + right: { ...defaultRequest, page: 1, perPage: 10 }, + }); + }); +}); + describe('Status', () => { describe('CasesStatusRequestRt', () => { const defaultRequest = { diff --git a/x-pack/plugins/cases/common/types/api/case/v1.ts b/x-pack/plugins/cases/common/types/api/case/v1.ts index 28beb03812aa5..228de9c1c281a 100644 --- a/x-pack/plugins/cases/common/types/api/case/v1.ts +++ b/x-pack/plugins/cases/common/types/api/case/v1.ts @@ -283,6 +283,21 @@ export const CasesFindRequestRt = rt.intersection([ paginationSchema({ maxPerPage: MAX_CASES_PER_PAGE }), ]); +export const CasesSearchRequestRt = rt.intersection([ + rt.exact( + rt.partial({ + /** + * custom fields of the case + */ + customFields: rt.record( + rt.string, + rt.array(rt.union([rt.string, rt.boolean, rt.number, rt.null])) + ), + }) + ), + CasesFindRequestRt, +]); + export const CasesFindResponseRt = rt.intersection([ rt.strict({ cases: rt.array(CaseRt), @@ -487,6 +502,7 @@ export type CaseResolveResponse = rt.TypeOf; export type CasesDeleteRequest = rt.TypeOf; export type CasesByAlertIDRequest = rt.TypeOf; export type CasesFindRequest = rt.TypeOf; +export type CasesSearchRequest = rt.TypeOf; export type CasesFindRequestSortFields = rt.TypeOf; export type CasesFindResponse = rt.TypeOf; export type CasePatchRequest = rt.TypeOf; diff --git a/x-pack/plugins/cases/public/components/all_cases/all_cases_list.test.tsx b/x-pack/plugins/cases/public/components/all_cases/all_cases_list.test.tsx index 10b55c0e979b3..4bd497a3c76f3 100644 --- a/x-pack/plugins/cases/public/components/all_cases/all_cases_list.test.tsx +++ b/x-pack/plugins/cases/public/components/all_cases/all_cases_list.test.tsx @@ -25,7 +25,7 @@ import { useGetCasesMockState, connectorsMock } from '../../containers/mock'; import { SortFieldCase, StatusAll } from '../../../common/ui/types'; import { CaseSeverity, CaseStatuses } from '../../../common/types/domain'; import { SECURITY_SOLUTION_OWNER } from '../../../common/constants'; -import { getEmptyTagValue } from '../empty_value'; +import { getEmptyCellValue } from '../empty_value'; import { useKibana } from '../../common/lib/kibana'; import { AllCasesList } from './all_cases_list'; import type { GetCasesColumn, UseCasesColumnsReturnValue } from './use_cases_columns'; @@ -48,7 +48,10 @@ import { userProfiles, userProfilesMap } from '../../containers/user_profiles/ap import { useBulkGetUserProfiles } from '../../containers/user_profiles/use_bulk_get_user_profiles'; import { useLicense } from '../../common/use_license'; import * as api from '../../containers/api'; +import { useGetCaseConfiguration } from '../../containers/configure/use_get_case_configuration'; +import { useCaseConfigureResponse } from '../configure_cases/__mock__'; +jest.mock('../../containers/configure/use_get_case_configuration'); jest.mock('../../containers/use_get_cases'); jest.mock('../../containers/use_get_action_license'); jest.mock('../../containers/use_get_tags'); @@ -64,6 +67,7 @@ jest.mock('../app/use_available_owners', () => ({ jest.mock('../../containers/use_update_case'); jest.mock('../../common/use_license'); +const useGetCaseConfigurationMock = useGetCaseConfiguration as jest.Mock; const useGetCasesMock = useGetCases as jest.Mock; const useGetTagsMock = useGetTags as jest.Mock; const useGetCurrentUserProfileMock = useGetCurrentUserProfile as jest.Mock; @@ -89,7 +93,7 @@ describe('AllCasesListGeneric', () => { const onRowClick = jest.fn(); const updateCaseProperty = jest.fn(); - const emptyTag = getEmptyTagValue().props.children; + const emptyTag = getEmptyCellValue().props.children; const defaultGetCases = { ...useGetCasesMockState, @@ -99,9 +103,11 @@ describe('AllCasesListGeneric', () => { filterStatus: CaseStatuses.open, handleIsLoading: jest.fn(), isLoadingCases: [], + isLoadingColumns: false, isSelectorView: false, userProfiles: new Map(), currentUserProfile: undefined, + selectedColumns: [], }; const removeMsFromDate = (value: string) => moment(value).format('YYYY-MM-DDTHH:mm:ss[Z]'); @@ -156,8 +162,9 @@ describe('AllCasesListGeneric', () => { useGetTagsMock.mockReturnValue({ data: ['coke', 'pepsi'], isLoading: false }); useGetCategoriesMock.mockReturnValue({ data: ['twix', 'snickers'], isLoading: false }); useGetCurrentUserProfileMock.mockReturnValue({ data: userProfiles[0], isLoading: false }); - useBulkGetUserProfilesMock.mockReturnValue({ data: userProfilesMap }); useGetConnectorsMock.mockImplementation(() => ({ data: connectorsMock, isLoading: false })); + useGetCaseConfigurationMock.mockImplementation(() => useCaseConfigureResponse); + useBulkGetUserProfilesMock.mockReturnValue({ data: userProfilesMap }); useUpdateCaseMock.mockReturnValue({ mutate: updateCaseProperty }); useLicenseMock.mockReturnValue({ isAtLeastPlatinum: () => false }); mockKibana(); @@ -1119,4 +1126,18 @@ describe('AllCasesListGeneric', () => { }); }); }); + + describe('Columns Popover', () => { + it('renders the columns popover correctly', async () => { + appMockRenderer.render(); + + expect(await screen.findByTestId('column-selection-popover-button')).toBeInTheDocument(); + }); + + it('does not render the columns popover when isSelectorView=true', () => { + appMockRenderer.render(); + + expect(screen.queryByTestId('column-selection-popover-button')).not.toBeInTheDocument(); + }); + }); }); diff --git a/x-pack/plugins/cases/public/components/all_cases/all_cases_list.tsx b/x-pack/plugins/cases/public/components/all_cases/all_cases_list.tsx index f915dbe0b7e38..75fe22f8e53b6 100644 --- a/x-pack/plugins/cases/public/components/all_cases/all_cases_list.tsx +++ b/x-pack/plugins/cases/public/components/all_cases/all_cases_list.tsx @@ -37,6 +37,7 @@ import { useGetCurrentUserProfile } from '../../containers/user_profiles/use_get import { getAllPermissionsExceptFrom, isReadOnlyPermissions } from '../../utils/permissions'; import { useIsLoadingCases } from './use_is_loading_cases'; import { useAllCasesState } from './use_all_cases_state'; +import { useCasesColumnsSelection } from './use_cases_columns_selection'; const ProgressLoader = styled(EuiProgress)` ${({ $isShow }: { $isShow: boolean }) => @@ -209,14 +210,16 @@ export const AllCasesList = React.memo( ] ); - const { columns } = useCasesColumns({ + const { selectedColumns, setSelectedColumns } = useCasesColumnsSelection(); + + const { columns, isLoadingColumns } = useCasesColumns({ filterStatus: filterOptions.status ?? StatusAll, userProfiles: userProfiles ?? new Map(), isSelectorView, connectors, onRowClick, - showSolutionColumn: !hasOwner && availableSolutions.length > 1, disableActions: selectedCases.length > 0, + selectedColumns, }); const pagination = useMemo( @@ -260,7 +263,7 @@ export const AllCasesList = React.memo( size="xs" color="accent" className="essentialAnimation" - $isShow={isLoading || isLoadingCases} + $isShow={isLoading || isLoadingCases || isLoadingColumns} /> {!isSelectorView ? : null} ( data={data} goToCreateCase={onRowClick ? onCreateCasePressed : undefined} isCasesLoading={isLoadingCases} + isLoadingColumns={isLoadingColumns} isCommentUpdating={isLoadingCases} isDataEmpty={isDataEmpty} isSelectorView={isSelectorView} @@ -302,6 +306,8 @@ export const AllCasesList = React.memo( tableRef={tableRef} tableRowProps={tableRowProps} deselectCases={deselectCases} + selectedColumns={selectedColumns} + onSelectedColumnsChange={setSelectedColumns} /> ); diff --git a/x-pack/plugins/cases/public/components/all_cases/assignees_column.tsx b/x-pack/plugins/cases/public/components/all_cases/assignees_column.tsx index 41e936a7021c0..c11c5a9d6a602 100644 --- a/x-pack/plugins/cases/public/components/all_cases/assignees_column.tsx +++ b/x-pack/plugins/cases/public/components/all_cases/assignees_column.tsx @@ -9,7 +9,7 @@ import React, { useCallback, useMemo, useState } from 'react'; import { EuiButtonEmpty, EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; import type { UserProfileWithAvatar } from '@kbn/user-profile-components'; import type { CaseUI } from '../../../common/ui/types'; -import { getEmptyTagValue } from '../empty_value'; +import { getEmptyCellValue } from '../empty_value'; import { UserToolTip } from '../user_profiles/user_tooltip'; import { useAssignees } from '../../containers/user_profiles/use_assignees'; import { getUsernameDataTestSubj } from '../user_profiles/data_test_subject'; @@ -58,7 +58,7 @@ const AssigneesColumnComponent: React.FC = ({ }, [allAssignees, isAvatarListExpanded, limitedAvatars, shouldShowExpandListButton]); if (allAssignees.length <= 0) { - return getEmptyTagValue(); + return getEmptyCellValue(); } return ( diff --git a/x-pack/plugins/cases/public/components/all_cases/columns_popover.test.tsx b/x-pack/plugins/cases/public/components/all_cases/columns_popover.test.tsx new file mode 100644 index 0000000000000..062ed4dd131f4 --- /dev/null +++ b/x-pack/plugins/cases/public/components/all_cases/columns_popover.test.tsx @@ -0,0 +1,173 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license 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 userEvent from '@testing-library/user-event'; + +import type { AppMockRenderer } from '../../common/mock'; +import { createAppMockRenderer } from '../../common/mock'; +import { ColumnsPopover } from './columns_popover'; + +describe('ColumnsPopover', () => { + let appMockRenderer: AppMockRenderer; + + beforeEach(() => { + appMockRenderer = createAppMockRenderer(); + jest.clearAllMocks(); + }); + + const selectedColumns = [ + { field: 'title', name: 'Title', isChecked: true }, + { field: 'category', name: 'Category', isChecked: false }, + { field: 'tags', name: 'Tags', isChecked: false }, + ]; + + it('renders correctly a list of selected columns', async () => { + appMockRenderer.render( + {}} /> + ); + + userEvent.click(await screen.findByTestId('column-selection-popover-button')); + + expect(await screen.findByTestId('column-selection-popover')).toBeInTheDocument(); + + selectedColumns.forEach(({ field, name, isChecked }) => { + expect(screen.getByTestId(`column-selection-switch-${field}`)).toHaveAttribute( + 'aria-checked', + isChecked.toString() + ); + expect(screen.getByText(name)).toBeInTheDocument(); + }); + }); + + it('clicking a switch calls onSelectedColumnsChange with the right params', async () => { + const onSelectedColumnsChange = jest.fn(); + + appMockRenderer.render( + + ); + + userEvent.click(await screen.findByTestId('column-selection-popover-button')); + userEvent.click( + await screen.findByTestId(`column-selection-switch-${selectedColumns[0].field}`), + undefined, + { skipPointerEventsCheck: true } + ); + + await waitFor(() => { + expect(onSelectedColumnsChange).toHaveBeenCalledWith([ + { ...selectedColumns[0], isChecked: false }, + selectedColumns[1], + selectedColumns[2], + ]); + }); + }); + + it('clicking Show All calls onSelectedColumnsChange with the right params', async () => { + const onSelectedColumnsChange = jest.fn(); + + appMockRenderer.render( + + ); + + userEvent.click(await screen.findByTestId('column-selection-popover-button')); + userEvent.click(await screen.findByTestId('column-selection-popover-show-all-button')); + + const onSelectedColumnsChangeCallParams = selectedColumns.map((column) => ({ + ...column, + isChecked: true, + })); + + await waitFor(() => { + expect(onSelectedColumnsChange).toHaveBeenCalledWith(onSelectedColumnsChangeCallParams); + }); + }); + + it('clicking Hide All calls onSelectedColumnsChange with the right params', async () => { + const onSelectedColumnsChange = jest.fn(); + + appMockRenderer.render( + + ); + + userEvent.click(await screen.findByTestId('column-selection-popover-button')); + userEvent.click(await screen.findByTestId('column-selection-popover-hide-all-button')); + + await waitFor(() => { + expect(onSelectedColumnsChange).toHaveBeenCalledWith( + selectedColumns.map((column) => ({ ...column, isChecked: false })) + ); + }); + }); + + it('searching for text changes the column list correctly', async () => { + appMockRenderer.render( + {}} /> + ); + + userEvent.click(await screen.findByTestId('column-selection-popover-button')); + userEvent.paste(await screen.findByTestId('column-selection-popover-search'), 'Title'); + + expect(await screen.findByTestId('column-selection-switch-title')).toBeInTheDocument(); + expect(screen.queryByTestId('column-selection-switch-category')).not.toBeInTheDocument(); + expect(screen.queryByTestId('column-selection-switch-tags')).not.toBeInTheDocument(); + }); + + it('searching for text does not change the list of selected columns', async () => { + const onSelectedColumnsChange = jest.fn(); + + appMockRenderer.render( + + ); + + userEvent.click(await screen.findByTestId('column-selection-popover-button')); + userEvent.paste(await screen.findByTestId('column-selection-popover-search'), 'Category'); + + expect(onSelectedColumnsChange).not.toHaveBeenCalled(); + }); + + it('searching for text hides the drag and drop icons', async () => { + appMockRenderer.render( + {}} /> + ); + + userEvent.click(await screen.findByTestId('column-selection-popover-button')); + + expect(await screen.findAllByTestId('column-selection-popover-draggable-icon')).toHaveLength(3); + + userEvent.paste(await screen.findByTestId('column-selection-popover-search'), 'Foobar'); + + expect( + await screen.queryByTestId('column-selection-popover-draggable-icon') + ).not.toBeInTheDocument(); + }); + + it('searching for text disables hideAll and showAll buttons', async () => { + appMockRenderer.render( + {}} /> + ); + + userEvent.click(await screen.findByTestId('column-selection-popover-button')); + userEvent.paste(await screen.findByTestId('column-selection-popover-search'), 'Foobar'); + + expect(await screen.findByTestId('column-selection-popover-show-all-button')).toBeDisabled(); + expect(await screen.findByTestId('column-selection-popover-hide-all-button')).toBeDisabled(); + }); +}); diff --git a/x-pack/plugins/cases/public/components/all_cases/columns_popover.tsx b/x-pack/plugins/cases/public/components/all_cases/columns_popover.tsx new file mode 100644 index 0000000000000..e95afcc159e98 --- /dev/null +++ b/x-pack/plugins/cases/public/components/all_cases/columns_popover.tsx @@ -0,0 +1,232 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license 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 { ChangeEvent } from 'react'; +import React, { useCallback, useMemo, useState } from 'react'; + +import type { DropResult } from '@elastic/eui'; + +import { + EuiFieldSearch, + EuiHighlight, + EuiPopoverFooter, + EuiPopoverTitle, + EuiFlexGroup, + EuiFlexItem, + EuiPopover, + EuiDragDropContext, + EuiButtonEmpty, + EuiDraggable, + EuiDroppable, + EuiPanel, + euiDragDropReorder, + EuiIcon, + EuiSwitch, + useEuiTheme, +} from '@elastic/eui'; + +import type { CasesColumnSelection } from './types'; + +import * as i18n from './translations'; + +interface Props { + selectedColumns: CasesColumnSelection[]; + onSelectedColumnsChange: (columns: CasesColumnSelection[]) => void; +} + +interface ToggleColumnsParams { + isChecked: boolean; + field?: string; +} + +export const ColumnsPopover: React.FC = ({ + selectedColumns, + onSelectedColumnsChange, +}: Props) => { + const { euiTheme } = useEuiTheme(); + + const [isPopoverOpen, setIsPopoverOpen] = useState(false); + + const togglePopover = useCallback(() => setIsPopoverOpen((prevValue) => !prevValue), []); + const closePopover = useCallback(() => setIsPopoverOpen(false), []); + + const [columnSearchText, setColumnSearchText] = useState(''); + + const isDragEnabled = columnSearchText.length === 0; + + const toggleColumns = useCallback( + ({ isChecked, field }: ToggleColumnsParams) => { + const newSelectedColumns = selectedColumns.map((column) => { + if (column.field === field || !field) { + return { ...column, isChecked }; + } + return column; + }); + + onSelectedColumnsChange(newSelectedColumns); + }, + [selectedColumns, onSelectedColumnsChange] + ); + + const showAll = useCallback(() => toggleColumns({ isChecked: true }), [toggleColumns]); + const hideAll = useCallback(() => toggleColumns({ isChecked: false }), [toggleColumns]); + + const onDragEnd = ({ source, destination }: DropResult) => { + if (source && destination) { + const reorderedColumns = euiDragDropReorder(selectedColumns, source.index, destination.index); + + onSelectedColumnsChange(reorderedColumns); + } + }; + + const filteredColumns = useMemo( + () => + selectedColumns.filter( + ({ name }) => name.toLowerCase().indexOf(columnSearchText.toLowerCase()) !== -1 + ), + [selectedColumns, columnSearchText] + ); + + return ( + + {i18n.COLUMNS} + + } + > + + ) => + setColumnSearchText(e.currentTarget.value) + } + data-test-subj="column-selection-popover-search" + /> + + + + + + {filteredColumns.map(({ field, name, isChecked }, idx) => ( + + {(provided) => ( + + + + {name} + + } + checked={isChecked} + data-test-subj={`column-selection-switch-${field}`} + onChange={(e) => toggleColumns({ field, isChecked: e.target.checked })} + compressed + labelProps={{ + style: { + textOverflow: 'ellipsis', + whiteSpace: 'nowrap', + width: '190px', + overflow: 'hidden', + }, + }} + /> + + {isDragEnabled && ( + + + + + + )} + + )} + + ))} + + + + + + + + + {i18n.SHOW_ALL} + + + + + {i18n.HIDE_ALL} + + + + + + ); +}; +ColumnsPopover.displayName = 'ColumnsPopover'; diff --git a/x-pack/plugins/cases/public/components/all_cases/table.tsx b/x-pack/plugins/cases/public/components/all_cases/table.tsx index ae60e942dc75a..e50d54b8a9d6f 100644 --- a/x-pack/plugins/cases/public/components/all_cases/table.tsx +++ b/x-pack/plugins/cases/public/components/all_cases/table.tsx @@ -14,7 +14,10 @@ import styled from 'styled-components'; import { CasesTableUtilityBar } from './utility_bar'; import { LinkButton } from '../links'; + import type { CasesFindResponseUI, CasesUI, CaseUI } from '../../../common/ui/types'; +import type { CasesColumnSelection } from './types'; + import * as i18n from './translations'; import { useCreateCaseNavigation } from '../../common/navigation'; import { useCasesContext } from '../cases_context/use_cases_context'; @@ -35,6 +38,9 @@ interface CasesTableProps { tableRef: MutableRefObject; tableRowProps: EuiBasicTableProps['rowProps']; deselectCases: () => void; + selectedColumns: CasesColumnSelection[]; + onSelectedColumnsChange: (columns: CasesColumnSelection[]) => void; + isLoadingColumns: boolean; } const Div = styled.div` @@ -57,6 +63,9 @@ export const CasesTable: FunctionComponent = ({ tableRef, tableRowProps, deselectCases, + selectedColumns, + onSelectedColumnsChange, + isLoadingColumns, }) => { const { permissions } = useCasesContext(); const { getCreateCaseUrl, navigateToCreateCase } = useCreateCaseNavigation(); @@ -72,7 +81,7 @@ export const CasesTable: FunctionComponent = ({ [goToCreateCase, navigateToCreateCase] ); - return isCasesLoading && isDataEmpty ? ( + return (isCasesLoading && isDataEmpty) || isLoadingColumns ? (
@@ -84,6 +93,8 @@ export const CasesTable: FunctionComponent = ({ totalCases={data.total ?? 0} selectedCases={selectedCases} deselectCases={deselectCases} + selectedColumns={selectedColumns} + onSelectedColumnsChange={onSelectedColumnsChange} /> { let appMockRender: AppMockRenderer; @@ -26,24 +46,35 @@ describe('useCasesColumns ', () => { filterStatus: CaseStatuses.open, userProfiles: userProfilesMap, isSelectorView: false, - showSolutionColumn: true, + selectedColumns: DEFAULT_SELECTED_COLUMNS, }; beforeEach(() => { jest.clearAllMocks(); appMockRender = createAppMockRenderer(); + useGetCaseConfigurationMock.mockImplementation(() => useCaseConfigureResponse); }); - it('return all columns correctly', async () => { + it('return all selected columns correctly', async () => { const license = licensingMock.createLicense({ license: { type: 'platinum' }, }); appMockRender = createAppMockRenderer({ license }); - const { result } = renderHook(() => useCasesColumns(useCasesColumnsProps), { - wrapper: appMockRender.AppWrapper, - }); + const { result } = renderHook( + () => + useCasesColumns({ + ...useCasesColumnsProps, + selectedColumns: DEFAULT_SELECTED_COLUMNS.map((element) => ({ + ...element, + isChecked: true, + })), + }), + { + wrapper: appMockRender.AppWrapper, + } + ); expect(result.current).toMatchInlineSnapshot(` Object { @@ -74,12 +105,6 @@ describe('useCasesColumns ', () => { "render": [Function], "width": "80px", }, - Object { - "align": "right", - "field": "owner", - "name": "Solution", - "render": [Function], - }, Object { "align": "right", "field": "totalComment", @@ -105,6 +130,12 @@ describe('useCasesColumns ', () => { "render": [Function], "sortable": true, }, + Object { + "field": "closedAt", + "name": "Closed on", + "render": [Function], + "sortable": true, + }, Object { "name": "External incident", "render": [Function], @@ -129,77 +160,22 @@ describe('useCasesColumns ', () => { "render": [Function], }, ], + "isLoadingColumns": false, } `); }); - it('returns the assignees column without the width specified when in the modal view', async () => { + it('only returns selected columns', async () => { const license = licensingMock.createLicense({ license: { type: 'platinum' }, }); appMockRender = createAppMockRenderer({ license }); - const { result } = renderHook( - () => useCasesColumns({ ...useCasesColumnsProps, isSelectorView: true }), - { - wrapper: appMockRender.AppWrapper, - } - ); - - expect(result.current).toMatchInlineSnapshot(` - Object { - "columns": Array [ - Object { - "field": "title", - "name": "Name", - "render": [Function], - "sortable": true, - "width": "55%", - }, - Object { - "field": "category", - "name": "Category", - "render": [Function], - "sortable": true, - "width": "100px", - }, - Object { - "field": "createdAt", - "name": "Created on", - "render": [Function], - "sortable": true, - }, - Object { - "field": "severity", - "name": "Severity", - "render": [Function], - "sortable": true, - "width": "90px", - }, - Object { - "align": "right", - "render": [Function], - }, - ], - } - `); - }); - - it('does not render the solution columns', async () => { - const license = licensingMock.createLicense({ - license: { type: 'platinum' }, + const { result } = renderHook(() => useCasesColumns(useCasesColumnsProps), { + wrapper: appMockRender.AppWrapper, }); - appMockRender = createAppMockRenderer({ license }); - - const { result } = renderHook( - () => useCasesColumns({ ...useCasesColumnsProps, showSolutionColumn: false }), - { - wrapper: appMockRender.AppWrapper, - } - ); - expect(result.current).toMatchInlineSnapshot(` Object { "columns": Array [ @@ -278,20 +254,24 @@ describe('useCasesColumns ', () => { "render": [Function], }, ], + "isLoadingColumns": false, } `); }); - it('does not return the alerts column', async () => { + it('returns the assignees column without the width specified when in the modal view', async () => { const license = licensingMock.createLicense({ license: { type: 'platinum' }, }); - appMockRender = createAppMockRenderer({ license, features: { alerts: { enabled: false } } }); + appMockRender = createAppMockRenderer({ license }); - const { result } = renderHook(() => useCasesColumns(useCasesColumnsProps), { - wrapper: appMockRender.AppWrapper, - }); + const { result } = renderHook( + () => useCasesColumns({ ...useCasesColumnsProps, isSelectorView: true }), + { + wrapper: appMockRender.AppWrapper, + } + ); expect(result.current).toMatchInlineSnapshot(` Object { @@ -301,31 +281,7 @@ describe('useCasesColumns ', () => { "name": "Name", "render": [Function], "sortable": true, - "width": "20%", - }, - Object { - "field": "assignees", - "name": "Assignees", - "render": [Function], - "width": "180px", - }, - Object { - "field": "tags", - "name": "Tags", - "render": [Function], - "width": "15%", - }, - Object { - "align": "right", - "field": "owner", - "name": "Solution", - "render": [Function], - }, - Object { - "align": "right", - "field": "totalComment", - "name": "Comments", - "render": [Function], + "width": "55%", }, Object { "field": "category", @@ -340,23 +296,6 @@ describe('useCasesColumns ', () => { "render": [Function], "sortable": true, }, - Object { - "field": "updatedAt", - "name": "Updated on", - "render": [Function], - "sortable": true, - }, - Object { - "name": "External incident", - "render": [Function], - "width": undefined, - }, - Object { - "field": "status", - "name": "Status", - "render": [Function], - "sortable": true, - }, Object { "field": "severity", "name": "Severity", @@ -366,18 +305,21 @@ describe('useCasesColumns ', () => { }, Object { "align": "right", - "name": "Actions", "render": [Function], }, ], + "isLoadingColumns": false, } `); }); - it('does not return the assignees column', async () => { - const { result } = renderHook(() => useCasesColumns(useCasesColumnsProps), { - wrapper: appMockRender.AppWrapper, - }); + it('shows the select button if isSelectorView=true', async () => { + const { result } = renderHook( + () => useCasesColumns({ ...useCasesColumnsProps, isSelectorView: true }), + { + wrapper: appMockRender.AppWrapper, + } + ); expect(result.current).toMatchInlineSnapshot(` Object { @@ -387,33 +329,56 @@ describe('useCasesColumns ', () => { "name": "Name", "render": [Function], "sortable": true, - "width": "20%", + "width": "55%", }, Object { - "field": "tags", - "name": "Tags", + "field": "category", + "name": "Category", "render": [Function], - "width": "15%", + "sortable": true, + "width": "100px", }, Object { - "align": "right", - "field": "totalAlerts", - "name": "Alerts", + "field": "createdAt", + "name": "Created on", "render": [Function], - "width": "80px", + "sortable": true, }, Object { - "align": "right", - "field": "owner", - "name": "Solution", + "field": "severity", + "name": "Severity", "render": [Function], + "sortable": true, + "width": "90px", }, Object { "align": "right", - "field": "totalComment", - "name": "Comments", "render": [Function], }, + ], + "isLoadingColumns": false, + } + `); + }); + + it('shows the correct columns if isSelectorView=true', async () => { + const { result } = renderHook( + () => useCasesColumns({ ...useCasesColumnsProps, isSelectorView: true }), + { + wrapper: appMockRender.AppWrapper, + } + ); + + expect(result.current).toMatchInlineSnapshot(` + Object { + "columns": Array [ + Object { + "field": "title", + "name": "Name", + "render": [Function], + "sortable": true, + "width": "55%", + }, Object { "field": "category", "name": "Category", @@ -427,23 +392,6 @@ describe('useCasesColumns ', () => { "render": [Function], "sortable": true, }, - Object { - "field": "updatedAt", - "name": "Updated on", - "render": [Function], - "sortable": true, - }, - Object { - "name": "External incident", - "render": [Function], - "width": undefined, - }, - Object { - "field": "status", - "name": "Status", - "render": [Function], - "sortable": true, - }, Object { "field": "severity", "name": "Severity", @@ -453,23 +401,20 @@ describe('useCasesColumns ', () => { }, Object { "align": "right", - "name": "Actions", "render": [Function], }, ], + "isLoadingColumns": false, } `); }); - it('shows the closedAt column if the filterStatus=closed', async () => { - appMockRender = createAppMockRenderer(); + it('does not shows the actions if the user does not have the right permissions', async () => { + appMockRender = createAppMockRenderer({ permissions: readCasesPermissions() }); - const { result } = renderHook( - () => useCasesColumns({ ...useCasesColumnsProps, filterStatus: CaseStatuses.closed }), - { - wrapper: appMockRender.AppWrapper, - } - ); + const { result } = renderHook(() => useCasesColumns(useCasesColumnsProps), { + wrapper: appMockRender.AppWrapper, + }); expect(result.current).toMatchInlineSnapshot(` Object { @@ -494,12 +439,6 @@ describe('useCasesColumns ', () => { "render": [Function], "width": "80px", }, - Object { - "align": "right", - "field": "owner", - "name": "Solution", - "render": [Function], - }, Object { "align": "right", "field": "totalComment", @@ -514,8 +453,8 @@ describe('useCasesColumns ', () => { "width": "100px", }, Object { - "field": "closedAt", - "name": "Closed on", + "field": "createdAt", + "name": "Created on", "render": [Function], "sortable": true, }, @@ -543,117 +482,46 @@ describe('useCasesColumns ', () => { "sortable": true, "width": "90px", }, - Object { - "align": "right", - "name": "Actions", - "render": [Function], - }, ], + "isLoadingColumns": false, } `); }); - it('shows the select button if isSelectorView=true', async () => { - const { result } = renderHook( - () => useCasesColumns({ ...useCasesColumnsProps, isSelectorView: true }), - { - wrapper: appMockRender.AppWrapper, - } - ); + it('returns custom field columns', async () => { + const textKey = 'text_key'; + const toggleKey = 'toggle_key'; - expect(result.current).toMatchInlineSnapshot(` - Object { - "columns": Array [ - Object { - "field": "title", - "name": "Name", - "render": [Function], - "sortable": true, - "width": "55%", - }, - Object { - "field": "category", - "name": "Category", - "render": [Function], - "sortable": true, - "width": "100px", - }, - Object { - "field": "createdAt", - "name": "Created on", - "render": [Function], - "sortable": true, - }, - Object { - "field": "severity", - "name": "Severity", - "render": [Function], - "sortable": true, - "width": "90px", - }, - Object { - "align": "right", - "render": [Function], - }, + const textLabel = 'Text Label'; + const toggleLabel = 'Toggle Label'; + + appMockRender = createAppMockRenderer({ permissions: readCasesPermissions() }); + useGetCaseConfigurationMock.mockImplementation(() => ({ + data: { + ...useCaseConfigureResponse.data, + customFields: [ + { key: textKey, label: textLabel, type: CustomFieldTypes.TEXT }, + { key: toggleKey, label: toggleLabel, type: CustomFieldTypes.TOGGLE }, ], - } - `); - }); + }, + isFetching: false, + })); - it('does not shows the actions if isSelectorView=true', async () => { const { result } = renderHook( - () => useCasesColumns({ ...useCasesColumnsProps, isSelectorView: true }), + () => + useCasesColumns({ + ...useCasesColumnsProps, + selectedColumns: [ + ...DEFAULT_SELECTED_COLUMNS, + { field: textKey, name: textLabel, isChecked: true }, + { field: toggleKey, name: toggleLabel, isChecked: true }, + ], + }), { wrapper: appMockRender.AppWrapper, } ); - expect(result.current).toMatchInlineSnapshot(` - Object { - "columns": Array [ - Object { - "field": "title", - "name": "Name", - "render": [Function], - "sortable": true, - "width": "55%", - }, - Object { - "field": "category", - "name": "Category", - "render": [Function], - "sortable": true, - "width": "100px", - }, - Object { - "field": "createdAt", - "name": "Created on", - "render": [Function], - "sortable": true, - }, - Object { - "field": "severity", - "name": "Severity", - "render": [Function], - "sortable": true, - "width": "90px", - }, - Object { - "align": "right", - "render": [Function], - }, - ], - } - `); - }); - - it('does not shows the actions if the user does not have the right permissions', async () => { - appMockRender = createAppMockRenderer({ permissions: readCasesPermissions() }); - - const { result } = renderHook(() => useCasesColumns(useCasesColumnsProps), { - wrapper: appMockRender.AppWrapper, - }); - expect(result.current).toMatchInlineSnapshot(` Object { "columns": Array [ @@ -677,12 +545,6 @@ describe('useCasesColumns ', () => { "render": [Function], "width": "80px", }, - Object { - "align": "right", - "field": "owner", - "name": "Solution", - "render": [Function], - }, Object { "align": "right", "field": "totalComment", @@ -726,7 +588,20 @@ describe('useCasesColumns ', () => { "sortable": true, "width": "90px", }, + Object { + "data-test-subj": "text-custom-field-column", + "name": "Text Label", + "render": [Function], + "width": "250px", + }, + Object { + "data-test-subj": "toggle-custom-field-column", + "name": "Toggle Label", + "render": [Function], + "width": "100px", + }, ], + "isLoadingColumns": false, } `); }); diff --git a/x-pack/plugins/cases/public/components/all_cases/use_cases_columns.tsx b/x-pack/plugins/cases/public/components/all_cases/use_cases_columns.tsx index 0863e51daef5c..6ef5dcae9fe6b 100644 --- a/x-pack/plugins/cases/public/components/all_cases/use_cases_columns.tsx +++ b/x-pack/plugins/cases/public/components/all_cases/use_cases_columns.tsx @@ -5,7 +5,7 @@ * 2.0. */ -import React, { useCallback } from 'react'; +import React, { useCallback, useMemo } from 'react'; import type { EuiTableActionsColumnType, EuiTableComputedColumnType, @@ -27,22 +27,22 @@ import type { UserProfileWithAvatar } from '@kbn/user-profile-components'; import { euiStyled } from '@kbn/kibana-react-plugin/common'; import type { ActionConnector } from '../../../common/types/domain'; -import { CaseSeverity, CaseStatuses } from '../../../common/types/domain'; +import { CaseSeverity } from '../../../common/types/domain'; import type { CaseUI } from '../../../common/ui/types'; -import { OWNER_INFO } from '../../../common/constants'; -import { getEmptyTagValue } from '../empty_value'; +import type { CasesColumnSelection } from './types'; +import { getEmptyCellValue } from '../empty_value'; import { FormattedRelativePreferenceDate } from '../formatted_date'; import { CaseDetailsLink } from '../links'; import * as i18n from './translations'; -import { ALERTS } from '../../common/translations'; import { useActions } from './use_actions'; +import { useCasesColumnsConfiguration } from './use_cases_columns_configuration'; import { useApplicationCapabilities, useKibana } from '../../common/lib/kibana'; import { TruncatedText } from '../truncated_text'; import { getConnectorIcon } from '../utils'; -import type { CasesOwners } from '../../client/helpers/can_use_cases'; import { severities } from '../severity/config'; -import { useCasesFeatures } from '../../common/use_cases_features'; import { AssigneesColumn } from './assignees_column'; +import { builderMap as customFieldsBuilderMap } from '../custom_fields/builder'; +import { useGetCaseConfiguration } from '../../containers/configure/use_get_case_configuration'; type CasesColumns = | EuiTableActionsColumnType @@ -67,34 +67,39 @@ const StyledEuiBadge = euiStyled(EuiBadge)` `; // to allow for ellipsis const renderStringField = (field: string, dataTestSubj: string) => - field != null ? {field} : getEmptyTagValue(); + field != null ? {field} : getEmptyCellValue(); export interface GetCasesColumn { filterStatus: string; userProfiles: Map; isSelectorView: boolean; + selectedColumns: CasesColumnSelection[]; connectors?: ActionConnector[]; onRowClick?: (theCase: CaseUI) => void; - showSolutionColumn?: boolean; disableActions?: boolean; } export interface UseCasesColumnsReturnValue { columns: CasesColumns[]; + isLoadingColumns: boolean; } export const useCasesColumns = ({ - filterStatus, userProfiles, isSelectorView, connectors = [], onRowClick, - showSolutionColumn, disableActions = false, + selectedColumns, }: GetCasesColumn): UseCasesColumnsReturnValue => { - const { isAlertsEnabled, caseAssignmentAuthorized } = useCasesFeatures(); + const casesColumnsConfig = useCasesColumnsConfiguration(isSelectorView); const { actions } = useActions({ disableActions }); + const { + data: { customFields }, + isFetching: isLoadingColumns, + } = useGetCaseConfiguration(); + const assignCaseAction = useCallback( async (theCase: CaseUI) => { if (onRowClick) { @@ -104,275 +109,270 @@ export const useCasesColumns = ({ [onRowClick] ); - const columns: CasesColumns[] = [ - { - field: 'title', - name: i18n.NAME, - sortable: true, - render: (title: string, theCase: CaseUI) => { - if (theCase.id != null && theCase.title != null) { - const caseDetailsLinkComponent = isSelectorView ? ( - theCase.title - ) : ( - - - - ); - - return caseDetailsLinkComponent; - } - return getEmptyTagValue(); + const columnsDict: Record = useMemo( + () => ({ + title: { + field: casesColumnsConfig.title.field, + name: casesColumnsConfig.title.name, + sortable: true, + render: (title: string, theCase: CaseUI) => { + if (theCase.id != null && theCase.title != null) { + const caseDetailsLinkComponent = isSelectorView ? ( + theCase.title + ) : ( + + + + ); + + return caseDetailsLinkComponent; + } + return getEmptyCellValue(); + }, + width: !isSelectorView ? '20%' : '55%', }, - width: !isSelectorView ? '20%' : '55%', - }, - ]; - - if (caseAssignmentAuthorized && !isSelectorView) { - columns.push({ - field: 'assignees', - name: i18n.ASSIGNEES, - render: (assignees: CaseUI['assignees']) => ( - - ), - width: '180px', - }); - } - - if (!isSelectorView) { - columns.push({ - field: 'tags', - name: i18n.TAGS, - render: (tags: CaseUI['tags']) => { - if (tags != null && tags.length > 0) { - const clampedBadges = ( - - {tags.map((tag: string, i: number) => ( - - {tag} - - ))} - - ); - - const unclampedBadges = ( - - {tags.map((tag: string, i: number) => ( - - {tag} - - ))} - - ); - - return ( - - {clampedBadges} - - ); - } - return getEmptyTagValue(); + assignees: { + field: casesColumnsConfig.assignees.field, + name: casesColumnsConfig.assignees.name, + render: (assignees: CaseUI['assignees']) => ( + + ), + width: '180px', }, - width: '15%', - }); - } - - if (isAlertsEnabled && !isSelectorView) { - columns.push({ - align: RIGHT_ALIGNMENT, - field: 'totalAlerts', - name: ALERTS, - render: (totalAlerts: CaseUI['totalAlerts']) => - totalAlerts != null - ? renderStringField(`${totalAlerts}`, `case-table-column-alertsCount`) - : getEmptyTagValue(), - width: !isSelectorView ? '80px' : '55px', - }); - } - - if (showSolutionColumn && !isSelectorView) { - columns.push({ - align: RIGHT_ALIGNMENT, - field: 'owner', - name: i18n.SOLUTION, - render: (caseOwner: CasesOwners) => { - const ownerInfo = OWNER_INFO[caseOwner]; - return ownerInfo ? ( - - ) : ( - getEmptyTagValue() - ); + tags: { + field: casesColumnsConfig.tags.field, + name: casesColumnsConfig.tags.name, + render: (tags: CaseUI['tags']) => { + if (tags != null && tags.length > 0) { + const clampedBadges = ( + + {tags.map((tag: string, i: number) => ( + + {tag} + + ))} + + ); + + const unclampedBadges = ( + + {tags.map((tag: string, i: number) => ( + + {tag} + + ))} + + ); + + return ( + + {clampedBadges} + + ); + } + return getEmptyCellValue(); + }, + width: '15%', }, - }); - } - - if (!isSelectorView) { - columns.push({ - align: RIGHT_ALIGNMENT, - field: 'totalComment', - name: i18n.COMMENTS, - render: (totalComment: CaseUI['totalComment']) => - totalComment != null - ? renderStringField(`${totalComment}`, `case-table-column-commentCount`) - : getEmptyTagValue(), - }); - } - - columns.push({ - field: 'category', - name: i18n.CATEGORY, - sortable: true, - render: (category: CaseUI['category']) => { - if (category != null) { - return {category}; - } - return getEmptyTagValue(); - }, - width: '100px', - }); - - if (filterStatus === CaseStatuses.closed) { - columns.push({ - field: 'closedAt', - name: i18n.CLOSED_ON, - sortable: true, - render: (closedAt: CaseUI['closedAt']) => { - if (closedAt != null) { - return ( - - - - ); - } - return getEmptyTagValue(); + totalAlerts: { + field: casesColumnsConfig.totalAlerts.field, + name: casesColumnsConfig.totalAlerts.name, + align: RIGHT_ALIGNMENT, + render: (totalAlerts: CaseUI['totalAlerts']) => + totalAlerts != null + ? renderStringField(`${totalAlerts}`, `case-table-column-alertsCount`) + : getEmptyCellValue(), + width: !isSelectorView ? '80px' : '55px', }, - }); - } else { - columns.push({ - field: 'createdAt', - name: i18n.CREATED_ON, - sortable: true, - render: (createdAt: CaseUI['createdAt']) => { - if (createdAt != null) { - return ( - - - - ); - } - return getEmptyTagValue(); + totalComment: { + field: casesColumnsConfig.totalComment.field, + name: casesColumnsConfig.totalComment.name, + align: RIGHT_ALIGNMENT, + render: (totalComment: CaseUI['totalComment']) => + totalComment != null + ? renderStringField(`${totalComment}`, `case-table-column-commentCount`) + : getEmptyCellValue(), }, - }); - } - - if (!isSelectorView) { - columns.push({ - field: 'updatedAt', - name: i18n.UPDATED_ON, - sortable: true, - render: (updatedAt: CaseUI['updatedAt']) => { - if (updatedAt != null) { - return ( - - - - ); - } - return getEmptyTagValue(); + category: { + field: casesColumnsConfig.category.field, + name: casesColumnsConfig.category.name, + sortable: true, + render: (category: CaseUI['category']) => { + if (category != null) { + return ( + {category} + ); + } + return getEmptyCellValue(); + }, + width: '100px', }, - }); - } - - if (!isSelectorView) { - columns.push( - { - name: i18n.EXTERNAL_INCIDENT, + closedAt: { + field: casesColumnsConfig.closedAt.field, + name: casesColumnsConfig.closedAt.name, + sortable: true, + render: (closedAt: CaseUI['closedAt']) => { + if (closedAt != null) { + return ( + + + + ); + } + return getEmptyCellValue(); + }, + }, + createdAt: { + field: casesColumnsConfig.createdAt.field, + name: casesColumnsConfig.createdAt.name, + sortable: true, + render: (createdAt: CaseUI['createdAt']) => { + if (createdAt != null) { + return ( + + + + ); + } + return getEmptyCellValue(); + }, + }, + updatedAt: { + field: casesColumnsConfig.updatedAt.field, + name: casesColumnsConfig.updatedAt.name, + sortable: true, + render: (updatedAt: CaseUI['updatedAt']) => { + if (updatedAt != null) { + return ( + + + + ); + } + return getEmptyCellValue(); + }, + }, + externalIncident: { + // no field + name: casesColumnsConfig.externalIncident.name, render: (theCase: CaseUI) => { if (theCase.id != null) { return ; } - return getEmptyTagValue(); + return getEmptyCellValue(); }, width: isSelectorView ? '80px' : undefined, }, - { - field: 'status', - name: i18n.STATUS, + status: { + field: casesColumnsConfig.status.field, + name: casesColumnsConfig.status.name, sortable: true, render: (status: CaseUI['status']) => { if (status != null) { return ; } - return getEmptyTagValue(); + return getEmptyCellValue(); }, - } - ); - } - columns.push({ - field: 'severity', - name: i18n.SEVERITY, - sortable: true, - render: (severity: CaseUI['severity']) => { - if (severity != null) { - const severityData = severities[severity ?? CaseSeverity.LOW]; - return ( - - {severityData.label} - - ); - } - return getEmptyTagValue(); - }, - width: '90px', - }); + }, + severity: { + field: casesColumnsConfig.severity.field, + name: casesColumnsConfig.severity.name, + sortable: true, + render: (severity: CaseUI['severity']) => { + if (severity != null) { + const severityData = severities[severity ?? CaseSeverity.LOW]; + return ( + + {severityData.label} + + ); + } + return getEmptyCellValue(); + }, + width: '90px', + }, + assignCaseAction: { + // no field + align: RIGHT_ALIGNMENT, + render: (theCase: CaseUI) => { + if (theCase.id != null) { + return ( + { + assignCaseAction(theCase); + }} + size="s" + > + {i18n.SELECT} + + ); + } + return getEmptyCellValue(); + }, + }, + }), + [assignCaseAction, casesColumnsConfig, connectors, isSelectorView, userProfiles] + ); - if (isSelectorView) { - columns.push({ - align: RIGHT_ALIGNMENT, - render: (theCase: CaseUI) => { - if (theCase.id != null) { - return ( - { - assignCaseAction(theCase); - }} - size="s" - > - {i18n.SELECT} - + // we need to extend the columnsDict with the columns of + // the customFields + customFields.forEach(({ key, type, label }) => { + if (type in customFieldsBuilderMap) { + const columnDefinition = customFieldsBuilderMap[type]().getEuiTableColumn({ label }); + + columnsDict[key] = { + ...columnDefinition, + render: (theCase: CaseUI) => { + const customField = theCase.customFields.find( + (element) => element.key === key && element.value !== null ); - } - return getEmptyTagValue(); - }, - }); - } - if (!isSelectorView && actions) { + if (!customField) { + return getEmptyCellValue(); + } + + return columnDefinition.render(customField); + }, + }; + } + }); + + const columns: CasesColumns[] = []; + + selectedColumns.forEach(({ field, isChecked }) => { + if ( + field in columnsDict && + (isChecked || isSelectorView) && + casesColumnsConfig[field].canDisplay + ) { + columns.push(columnsDict[field]); + } + }); + + if (isSelectorView) { + columns.push(columnsDict.assignCaseAction); + } else if (actions) { columns.push(actions); } - return { columns }; + return { columns, isLoadingColumns }; }; interface Props { diff --git a/x-pack/plugins/cases/public/components/all_cases/use_cases_columns_configuration.test.tsx b/x-pack/plugins/cases/public/components/all_cases/use_cases_columns_configuration.test.tsx new file mode 100644 index 0000000000000..761da1d6316e8 --- /dev/null +++ b/x-pack/plugins/cases/public/components/all_cases/use_cases_columns_configuration.test.tsx @@ -0,0 +1,199 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { licensingMock } from '@kbn/licensing-plugin/public/mocks'; +import { renderHook } from '@testing-library/react-hooks'; + +import type { AppMockRenderer } from '../../common/mock'; +import { createAppMockRenderer } from '../../common/mock'; +import { useCasesFeatures } from '../../common/use_cases_features'; + +import { useCasesColumnsConfiguration } from './use_cases_columns_configuration'; +import { useGetCaseConfiguration } from '../../containers/configure/use_get_case_configuration'; +import { useCaseConfigureResponse } from '../configure_cases/__mock__'; +import { CustomFieldTypes } from '../../../common/types/domain'; + +jest.mock('../../common/use_cases_features'); +jest.mock('../../containers/configure/use_get_case_configuration'); + +const useGetCaseConfigurationMock = useGetCaseConfiguration as jest.Mock; +const useCasesFeaturesMock = useCasesFeatures as jest.Mock; + +describe('useCasesColumnsConfiguration ', () => { + let appMockRender: AppMockRenderer; + const license = licensingMock.createLicense({ + license: { type: 'platinum' }, + }); + + beforeEach(() => { + jest.clearAllMocks(); + appMockRender = createAppMockRenderer({ license }); + useCasesFeaturesMock.mockReturnValue({ + caseAssignmentAuthorized: true, + isAlertsEnabled: true, + }); + useGetCaseConfigurationMock.mockImplementation(() => useCaseConfigureResponse); + }); + + it('returns all columns correctly', async () => { + const { result } = renderHook(() => useCasesColumnsConfiguration(), { + wrapper: appMockRender.AppWrapper, + }); + + expect(result.current).toMatchInlineSnapshot(` + Object { + "assignees": Object { + "canDisplay": true, + "field": "assignees", + "isCheckedDefault": true, + "name": "Assignees", + }, + "category": Object { + "canDisplay": true, + "field": "category", + "isCheckedDefault": true, + "name": "Category", + }, + "closedAt": Object { + "canDisplay": true, + "field": "closedAt", + "isCheckedDefault": false, + "name": "Closed on", + }, + "createdAt": Object { + "canDisplay": true, + "field": "createdAt", + "isCheckedDefault": true, + "name": "Created on", + }, + "externalIncident": Object { + "canDisplay": true, + "field": "externalIncident", + "isCheckedDefault": true, + "name": "External incident", + }, + "severity": Object { + "canDisplay": true, + "field": "severity", + "isCheckedDefault": true, + "name": "Severity", + }, + "status": Object { + "canDisplay": true, + "field": "status", + "isCheckedDefault": true, + "name": "Status", + }, + "tags": Object { + "canDisplay": true, + "field": "tags", + "isCheckedDefault": true, + "name": "Tags", + }, + "title": Object { + "canDisplay": true, + "field": "title", + "isCheckedDefault": true, + "name": "Name", + }, + "totalAlerts": Object { + "canDisplay": true, + "field": "totalAlerts", + "isCheckedDefault": true, + "name": "Alerts", + }, + "totalComment": Object { + "canDisplay": true, + "field": "totalComment", + "isCheckedDefault": true, + "name": "Comments", + }, + "updatedAt": Object { + "canDisplay": true, + "field": "updatedAt", + "isCheckedDefault": true, + "name": "Updated on", + }, + } + `); + }); + + it('cannot display assignees when case assignment is not authorized', async () => { + useCasesFeaturesMock.mockReturnValue({ + caseAssignmentAuthorized: false, + isAlertsEnabled: true, + }); + + const { result } = renderHook(() => useCasesColumnsConfiguration(), { + wrapper: appMockRender.AppWrapper, + }); + + expect(result.current.assignees).toMatchInlineSnapshot(` + Object { + "canDisplay": false, + "field": "assignees", + "isCheckedDefault": true, + "name": "Assignees", + } + `); + }); + + it('cannot display alerts if alerts are not enabled', async () => { + useCasesFeaturesMock.mockReturnValue({ + caseAssignmentAuthorized: true, + isAlertsEnabled: false, + }); + + const { result } = renderHook(() => useCasesColumnsConfiguration(), { + wrapper: appMockRender.AppWrapper, + }); + + expect(result.current.totalAlerts).toMatchInlineSnapshot(` + Object { + "canDisplay": false, + "field": "totalAlerts", + "isCheckedDefault": true, + "name": "Alerts", + } + `); + }); + + it('includes custom field columns correctly', async () => { + const textKey = 'text_key'; + const toggleKey = 'toggle_key'; + + const textLabel = 'Text Label'; + const toggleLabel = 'Toggle Label'; + + useGetCaseConfigurationMock.mockImplementation(() => ({ + data: { + ...useCaseConfigureResponse.data, + customFields: [ + { key: textKey, label: textLabel, type: CustomFieldTypes.TEXT }, + { key: toggleKey, label: toggleLabel, type: CustomFieldTypes.TOGGLE }, + ], + }, + })); + + const { result } = renderHook(() => useCasesColumnsConfiguration(), { + wrapper: appMockRender.AppWrapper, + }); + + expect(result.current[textKey]).toEqual({ + field: textKey, + name: textLabel, + canDisplay: true, + isCheckedDefault: false, + }); + expect(result.current[toggleKey]).toEqual({ + field: toggleKey, + name: toggleLabel, + canDisplay: true, + isCheckedDefault: false, + }); + }); +}); diff --git a/x-pack/plugins/cases/public/components/all_cases/use_cases_columns_configuration.tsx b/x-pack/plugins/cases/public/components/all_cases/use_cases_columns_configuration.tsx new file mode 100644 index 0000000000000..fd795320bcf99 --- /dev/null +++ b/x-pack/plugins/cases/public/components/all_cases/use_cases_columns_configuration.tsx @@ -0,0 +1,119 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import * as i18n from './translations'; +import { ALERTS } from '../../common/translations'; +import { useCasesFeatures } from '../../common/use_cases_features'; +import { useGetCaseConfiguration } from '../../containers/configure/use_get_case_configuration'; + +export type CasesColumnsConfiguration = Record< + string, + { + field: string; + name: string; + canDisplay: boolean; + isCheckedDefault: boolean; + } +>; + +export const useCasesColumnsConfiguration = ( + isSelectorView?: boolean +): CasesColumnsConfiguration => { + const { isAlertsEnabled, caseAssignmentAuthorized } = useCasesFeatures(); + const { + data: { customFields }, + } = useGetCaseConfiguration(); + + const canDisplayDefault = true; + + const result: CasesColumnsConfiguration = { + title: { + field: 'title', + name: i18n.NAME, + canDisplay: canDisplayDefault, + isCheckedDefault: true, + }, + assignees: { + field: 'assignees', + name: i18n.ASSIGNEES, + canDisplay: caseAssignmentAuthorized && !isSelectorView, + isCheckedDefault: true, + }, + tags: { + field: 'tags', + name: i18n.TAGS, + canDisplay: canDisplayDefault && !isSelectorView, + isCheckedDefault: true, + }, + totalAlerts: { + field: 'totalAlerts', + name: ALERTS, + canDisplay: isAlertsEnabled && !isSelectorView, + isCheckedDefault: true, + }, + totalComment: { + field: 'totalComment', + name: i18n.COMMENTS, + canDisplay: canDisplayDefault && !isSelectorView, + isCheckedDefault: true, + }, + category: { + field: 'category', + name: i18n.CATEGORY, + canDisplay: canDisplayDefault, + isCheckedDefault: true, + }, + closedAt: { + field: 'closedAt', + name: i18n.CLOSED_ON, + canDisplay: canDisplayDefault && !isSelectorView, + isCheckedDefault: false, + }, + createdAt: { + field: 'createdAt', + name: i18n.CREATED_ON, + canDisplay: canDisplayDefault, + isCheckedDefault: true, + }, + updatedAt: { + field: 'updatedAt', + name: i18n.UPDATED_ON, + canDisplay: canDisplayDefault && !isSelectorView, + isCheckedDefault: true, + }, + externalIncident: { + field: 'externalIncident', + name: i18n.EXTERNAL_INCIDENT, + canDisplay: canDisplayDefault && !isSelectorView, + isCheckedDefault: true, + }, + status: { + field: 'status', + name: i18n.STATUS, + canDisplay: canDisplayDefault && !isSelectorView, + isCheckedDefault: true, + }, + severity: { + field: 'severity', + name: i18n.SEVERITY, + canDisplay: canDisplayDefault, + isCheckedDefault: true, + }, + }; + + // we need to extend the configuration with the customFields + customFields.forEach(({ key, label }) => { + result[key] = { + field: key, + name: label, + canDisplay: canDisplayDefault && !isSelectorView, + isCheckedDefault: false, + }; + }); + + return result; +}; diff --git a/x-pack/plugins/cases/public/components/all_cases/use_cases_columns_selection.test.tsx b/x-pack/plugins/cases/public/components/all_cases/use_cases_columns_selection.test.tsx new file mode 100644 index 0000000000000..98f4e33ee9132 --- /dev/null +++ b/x-pack/plugins/cases/public/components/all_cases/use_cases_columns_selection.test.tsx @@ -0,0 +1,125 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { licensingMock } from '@kbn/licensing-plugin/public/mocks'; +import { renderHook } from '@testing-library/react-hooks'; + +import type { AppMockRenderer } from '../../common/mock'; + +import { createAppMockRenderer } from '../../common/mock'; +import { useCasesColumnsSelection } from './use_cases_columns_selection'; +import { useCasesColumnsConfiguration } from './use_cases_columns_configuration'; + +jest.mock('./use_cases_columns_configuration'); + +const useCasesColumnsConfigurationMock = useCasesColumnsConfiguration as jest.Mock; + +const localStorageKey = 'testAppId.cases.list.tableColumns'; +const casesColumnsConfig = { + title: { + field: 'title', + name: 'Name', + canDisplay: true, + }, + assignees: { + field: 'assignees', + name: 'Assignees', + canDisplay: true, + }, + tags: { + field: 'tags', + name: 'Tags', + canDisplay: true, + }, +}; + +describe('useCasesColumnsSelection ', () => { + let appMockRender: AppMockRenderer; + const license = licensingMock.createLicense({ + license: { type: 'platinum' }, + }); + + beforeEach(() => { + appMockRender = createAppMockRenderer({ license }); + + useCasesColumnsConfigurationMock.mockReturnValue(casesColumnsConfig); + + localStorage.clear(); + }); + + afterEach(() => { + jest.clearAllMocks(); + }); + + it('returns the expected selectedColumns when the localstorage is empty', async () => { + const { result } = renderHook(() => useCasesColumnsSelection(), { + wrapper: appMockRender.AppWrapper, + }); + + expect(result.current).toMatchInlineSnapshot(` + Object { + "selectedColumns": Array [ + Object { + "field": "title", + "isChecked": undefined, + "name": "Name", + }, + Object { + "field": "assignees", + "isChecked": undefined, + "name": "Assignees", + }, + Object { + "field": "tags", + "isChecked": undefined, + "name": "Tags", + }, + ], + "setSelectedColumns": [Function], + } + `); + }); + + it('calls mergeSelectedColumnsWithConfiguration with existing localstorage value', async () => { + const selectedColumns = [ + { + field: 'title', + name: 'Name', + isChecked: false, + }, + ]; + + localStorage.setItem(localStorageKey, JSON.stringify(selectedColumns)); + + const { result } = renderHook(() => useCasesColumnsSelection(), { + wrapper: appMockRender.AppWrapper, + }); + + expect(result.current).toMatchInlineSnapshot(` + Object { + "selectedColumns": Array [ + Object { + "field": "title", + "isChecked": false, + "name": "Name", + }, + Object { + "field": "assignees", + "isChecked": undefined, + "name": "Assignees", + }, + Object { + "field": "tags", + "isChecked": undefined, + "name": "Tags", + }, + ], + "setSelectedColumns": [Function], + } + `); + }); +}); diff --git a/x-pack/plugins/cases/public/components/all_cases/use_cases_columns_selection.tsx b/x-pack/plugins/cases/public/components/all_cases/use_cases_columns_selection.tsx new file mode 100644 index 0000000000000..a7c32ee939a19 --- /dev/null +++ b/x-pack/plugins/cases/public/components/all_cases/use_cases_columns_selection.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 useLocalStorage from 'react-use/lib/useLocalStorage'; + +import type { CasesColumnSelection } from './types'; + +import { LOCAL_STORAGE_KEYS } from '../../../common/constants'; +import { useCasesContext } from '../cases_context/use_cases_context'; +import { useCasesColumnsConfiguration } from './use_cases_columns_configuration'; +import { mergeSelectedColumnsWithConfiguration } from './utils'; + +const getTableColumnsLocalStorageKey = (appId: string) => { + const filteringKey = LOCAL_STORAGE_KEYS.casesTableColumns; + return `${appId}.${filteringKey}`; +}; + +export function useCasesColumnsSelection() { + const { appId } = useCasesContext(); + const casesColumnsConfig = useCasesColumnsConfiguration(); + + const [selectedColumns, setSelectedColumns] = useLocalStorage( + getTableColumnsLocalStorageKey(appId) + ); + + const columns = selectedColumns || []; + + return { + selectedColumns: mergeSelectedColumnsWithConfiguration({ + selectedColumns: columns, + casesColumnsConfig, + }), + setSelectedColumns, + }; +} diff --git a/x-pack/plugins/cases/public/components/all_cases/utility_bar.test.tsx b/x-pack/plugins/cases/public/components/all_cases/utility_bar.test.tsx index 4d740c2fb9552..ce776e77e8304 100644 --- a/x-pack/plugins/cases/public/components/all_cases/utility_bar.test.tsx +++ b/x-pack/plugins/cases/public/components/all_cases/utility_bar.test.tsx @@ -34,6 +34,8 @@ describe('Severity form field', () => { pageSize: 10, totalItemCount: 5, }, + selectedColumns: [], + onSelectedColumnsChange: jest.fn(), }; beforeEach(() => { @@ -88,11 +90,23 @@ describe('Severity form field', () => { pageIndex: 1, totalItemCount: 0, }, + selectedColumns: [], + onSelectedColumnsChange: jest.fn(), }; appMockRender.render(); expect(screen.getByText('Showing 0 of 0 cases')).toBeInTheDocument(); }); + it('renders columns popover button when isSelectorView=False', async () => { + appMockRender.render(); + expect(screen.getByTestId('column-selection-popover-button')).toBeInTheDocument(); + }); + + it('does not render columns popover button when isSelectorView=True', async () => { + appMockRender.render(); + expect(screen.queryByTestId('column-selection-popover-button')).not.toBeInTheDocument(); + }); + it('opens the bulk actions correctly', async () => { appMockRender.render(); diff --git a/x-pack/plugins/cases/public/components/all_cases/utility_bar.tsx b/x-pack/plugins/cases/public/components/all_cases/utility_bar.tsx index 2c2aebdb30bb2..ee80e0ffb38b1 100644 --- a/x-pack/plugins/cases/public/components/all_cases/utility_bar.tsx +++ b/x-pack/plugins/cases/public/components/all_cases/utility_bar.tsx @@ -23,10 +23,12 @@ import { } from '@elastic/eui'; import * as i18n from './translations'; import type { CasesUI } from '../../../common/ui/types'; +import type { CasesColumnSelection } from './types'; import { MAX_DOCS_PER_PAGE } from '../../../common/constants'; import { useRefreshCases } from './use_on_refresh_cases'; import { useBulkActions } from './use_bulk_actions'; import { useCasesContext } from '../cases_context/use_cases_context'; +import { ColumnsPopover } from './columns_popover'; interface Props { isSelectorView?: boolean; @@ -34,10 +36,20 @@ interface Props { selectedCases: CasesUI; deselectCases: () => void; pagination: Pagination; + selectedColumns: CasesColumnSelection[]; + onSelectedColumnsChange: (columns: CasesColumnSelection[]) => void; } export const CasesTableUtilityBar: FunctionComponent = React.memo( - ({ isSelectorView, totalCases, selectedCases, deselectCases, pagination }) => { + ({ + isSelectorView, + totalCases, + selectedCases, + deselectCases, + pagination, + selectedColumns, + onSelectedColumnsChange, + }) => { const { euiTheme } = useEuiTheme(); const refreshCases = useRefreshCases(); const { permissions, appId } = useCasesContext(); @@ -126,8 +138,8 @@ export const CasesTableUtilityBar: FunctionComponent = React.memo( return ( <> = React.memo( paddingBottom: euiTheme.size.s, }} > - - - {i18n.SHOWING_CASES(totalCases, visibleCases)} - - - - - {!isSelectorView && showBulkActions && ( - <> - - - {i18n.SHOWING_SELECTED_CASES(selectedCases.length)} - - - - + + + + {i18n.SHOWING_CASES(totalCases, visibleCases)} + + + + + {!isSelectorView && showBulkActions && ( + <> + + + {i18n.SHOWING_SELECTED_CASES(selectedCases.length)} + + + + + {i18n.BULK_ACTIONS} + + } > - {i18n.BULK_ACTIONS} - - } + + + + + )} + + - - + {i18n.REFRESH} + - - )} - - - {i18n.REFRESH} - + + {!isSelectorView && ( + + + + )}
{modals} {flyouts} diff --git a/x-pack/plugins/cases/public/components/all_cases/utils.test.tsx b/x-pack/plugins/cases/public/components/all_cases/utils.test.tsx index 6606f2e18d735..5e5d91e9a5926 100644 --- a/x-pack/plugins/cases/public/components/all_cases/utils.test.tsx +++ b/x-pack/plugins/cases/public/components/all_cases/utils.test.tsx @@ -5,7 +5,10 @@ * 2.0. */ -import { parseUrlQueryParams } from './utils'; +import type { CasesColumnsConfiguration } from './use_cases_columns_configuration'; +import type { CasesColumnSelection } from './types'; + +import { mergeSelectedColumnsWithConfiguration, parseUrlQueryParams } from './utils'; import { DEFAULT_QUERY_PARAMS } from '../../containers/use_get_cases'; const DEFAULT_STRING_QUERY_PARAMS = { @@ -68,4 +71,78 @@ describe('utils', () => { ).toStrictEqual(DEFAULT_QUERY_PARAMS); }); }); + + describe('mergeSelectedColumnsWithConfiguration', () => { + const mockConfiguration: CasesColumnsConfiguration = { + foo: { field: 'foo', name: 'foo', canDisplay: true, isCheckedDefault: true }, + bar: { field: 'bar', name: 'bar', canDisplay: true, isCheckedDefault: true }, + }; + const mockSelectedColumns: CasesColumnSelection[] = [ + { field: 'foo', name: 'foo', isChecked: true }, + { field: 'bar', name: 'bar', isChecked: true }, + ]; + + it('does not return selectedColumns without a matching configuration', () => { + expect( + mergeSelectedColumnsWithConfiguration({ + selectedColumns: [ + ...mockSelectedColumns, + { field: 'foobar', name: 'foobar', isChecked: true }, + ], + casesColumnsConfig: mockConfiguration, + }) + ).toStrictEqual(mockSelectedColumns); + }); + + it('does not return selectedColumns with canDisplay value false in configuration', () => { + expect( + mergeSelectedColumnsWithConfiguration({ + selectedColumns: mockSelectedColumns, + casesColumnsConfig: { + ...mockConfiguration, + bar: { ...mockConfiguration.bar, canDisplay: false }, + }, + }) + ).toStrictEqual([mockSelectedColumns[0]]); + }); + + it('does not return selectedColumns without a field in the configuration', () => { + expect( + mergeSelectedColumnsWithConfiguration({ + selectedColumns: mockSelectedColumns, + casesColumnsConfig: { + ...mockConfiguration, + bar: { ...mockConfiguration.bar, field: '' }, + }, + }) + ).toStrictEqual([mockSelectedColumns[0]]); + }); + + it('result contains columns missing in the selectedColumns with isChecked false', () => { + expect( + mergeSelectedColumnsWithConfiguration({ + selectedColumns: [], + casesColumnsConfig: mockConfiguration, + }) + ).toStrictEqual([ + { field: 'foo', name: 'foo', isChecked: true }, + { field: 'bar', name: 'bar', isChecked: true }, + ]); + }); + + it('result does not include columns missing in the selectedColumns when canDisplay=false', () => { + expect( + mergeSelectedColumnsWithConfiguration({ + selectedColumns: [], + casesColumnsConfig: { + ...mockConfiguration, + foobar: { field: 'foobar', name: 'foobar', canDisplay: false, isCheckedDefault: false }, + }, + }) + ).toStrictEqual([ + { field: 'foo', name: 'foo', isChecked: true }, + { field: 'bar', name: 'bar', isChecked: true }, + ]); + }); + }); }); diff --git a/x-pack/plugins/cases/public/components/all_cases/utils.ts b/x-pack/plugins/cases/public/components/all_cases/utils.ts index 834bfa1085755..82ba4484701a8 100644 --- a/x-pack/plugins/cases/public/components/all_cases/utils.ts +++ b/x-pack/plugins/cases/public/components/all_cases/utils.ts @@ -5,7 +5,10 @@ * 2.0. */ +import { difference } from 'lodash'; import type { ParsedUrlQueryParams, PartialQueryParams } from '../../../common/ui/types'; +import type { CasesColumnSelection } from './types'; +import type { CasesColumnsConfiguration } from './use_cases_columns_configuration'; export const parseUrlQueryParams = (parsedUrlParams: ParsedUrlQueryParams): PartialQueryParams => { const urlParams: PartialQueryParams = { @@ -28,3 +31,45 @@ export const parseUrlQueryParams = (parsedUrlParams: ParsedUrlQueryParams): Part return urlParams; }; + +export const mergeSelectedColumnsWithConfiguration = ({ + selectedColumns, + casesColumnsConfig, +}: { + selectedColumns: CasesColumnSelection[]; + casesColumnsConfig: CasesColumnsConfiguration; +}): CasesColumnSelection[] => { + const result = selectedColumns.reduce((accumulator, { field, isChecked }) => { + if ( + field in casesColumnsConfig && + casesColumnsConfig[field].field !== '' && + casesColumnsConfig[field].canDisplay + ) { + accumulator.push({ + field: casesColumnsConfig[field].field, + name: casesColumnsConfig[field].name, + isChecked, + }); + } + return accumulator; + }, [] as CasesColumnSelection[]); + + // This will include any new customFields and/or changes to the case attributes + const missingColumns = difference( + Object.keys(casesColumnsConfig), + selectedColumns.map(({ field }) => field) + ); + + missingColumns.forEach((field) => { + // can be an empty string + if (casesColumnsConfig[field].field && casesColumnsConfig[field].canDisplay) { + result.push({ + field: casesColumnsConfig[field].field, + name: casesColumnsConfig[field].name, + isChecked: casesColumnsConfig[field].isCheckedDefault, + }); + } + }); + + return result; +}; diff --git a/x-pack/plugins/cases/public/components/case_view/metrics/status.tsx b/x-pack/plugins/cases/public/components/case_view/metrics/status.tsx index d77d6466a102e..d6c93417cbcd9 100644 --- a/x-pack/plugins/cases/public/components/case_view/metrics/status.tsx +++ b/x-pack/plugins/cases/public/components/case_view/metrics/status.tsx @@ -21,7 +21,7 @@ import { } from './translations'; import { getMaybeDate } from '../../formatted_date/maybe_date'; import { FormattedRelativePreferenceDate } from '../../formatted_date'; -import { getEmptyTagValue } from '../../empty_value'; +import { getEmptyCellValue } from '../../empty_value'; export const CaseStatusMetrics = React.memo( ({ metrics, features }: { metrics: SingleCaseMetrics; features: SingleCaseMetricsFeature[] }) => { @@ -112,7 +112,7 @@ const useGetLifespanMetrics = ( const CreationDate: React.FC<{ date: string }> = React.memo(({ date }) => { const creationDate = getMaybeDate(date); if (!creationDate.isValid()) { - return getEmptyTagValue(); + return getEmptyCellValue(); } return ( @@ -127,7 +127,7 @@ CreationDate.displayName = 'CreationDate'; const getInProgressDuration = (duration: number) => { if (duration <= 0) { - return getEmptyTagValue(); + return getEmptyCellValue(); } return formatDuration(duration); @@ -190,7 +190,7 @@ CaseStatusMetricsOpenCloseDuration.displayName = 'OpenCloseDuration'; const getOpenCloseDurationText = (value: string | undefined, reopens: string[]) => { if (value == null) { - return getEmptyTagValue(); + return getEmptyCellValue(); } else if (reopens.length > 0) { return `${value} ${CASE_REOPENED}`; } diff --git a/x-pack/plugins/cases/public/components/configure_cases/__mock__/index.tsx b/x-pack/plugins/cases/public/components/configure_cases/__mock__/index.tsx index 908d270d9cc1e..c44e5fbc22312 100644 --- a/x-pack/plugins/cases/public/components/configure_cases/__mock__/index.tsx +++ b/x-pack/plugins/cases/public/components/configure_cases/__mock__/index.tsx @@ -32,6 +32,7 @@ export const useCaseConfigureResponse = { id: '', }, isLoading: false, + isFetching: false, refetch: jest.fn(), }; diff --git a/x-pack/plugins/cases/public/components/custom_fields/text/configure_text_field.test.ts b/x-pack/plugins/cases/public/components/custom_fields/text/configure_text_field.test.ts index 0b5a4966ee730..9ce931b1fa293 100644 --- a/x-pack/plugins/cases/public/components/custom_fields/text/configure_text_field.test.ts +++ b/x-pack/plugins/cases/public/components/custom_fields/text/configure_text_field.test.ts @@ -18,6 +18,7 @@ describe('configureTextCustomFieldFactory ', () => { expect(builder).toEqual({ id: 'text', label: 'Text', + getEuiTableColumn: expect.any(Function), build: expect.any(Function), }); }); diff --git a/x-pack/plugins/cases/public/components/custom_fields/text/configure_text_field.ts b/x-pack/plugins/cases/public/components/custom_fields/text/configure_text_field.ts index 0081a2449a3f8..908d7c678d3dd 100644 --- a/x-pack/plugins/cases/public/components/custom_fields/text/configure_text_field.ts +++ b/x-pack/plugins/cases/public/components/custom_fields/text/configure_text_field.ts @@ -4,11 +4,12 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ - import type { CustomFieldFactory } from '../types'; import type { CaseCustomFieldText } from '../../../../common/types/domain'; + import { CustomFieldTypes } from '../../../../common/types/domain'; import * as i18n from '../translations'; +import { getEuiTableColumn } from './get_eui_table_column'; import { Edit } from './edit'; import { View } from './view'; import { Configure } from './configure'; @@ -17,6 +18,7 @@ import { Create } from './create'; export const configureTextCustomFieldFactory: CustomFieldFactory = () => ({ id: CustomFieldTypes.TEXT, label: i18n.TEXT_LABEL, + getEuiTableColumn, build: () => ({ Configure, Edit, diff --git a/x-pack/plugins/cases/public/components/custom_fields/text/get_eui_table_column.test.tsx b/x-pack/plugins/cases/public/components/custom_fields/text/get_eui_table_column.test.tsx new file mode 100644 index 0000000000000..4330452fddeef --- /dev/null +++ b/x-pack/plugins/cases/public/components/custom_fields/text/get_eui_table_column.test.tsx @@ -0,0 +1,46 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import React from 'react'; + +import { screen } from '@testing-library/react'; + +import { CustomFieldTypes } from '../../../../common/types/domain'; +import type { AppMockRenderer } from '../../../common/mock'; +import { createAppMockRenderer } from '../../../common/mock'; +import { getEuiTableColumn } from './get_eui_table_column'; + +describe('getEuiTableColumn ', () => { + let appMockRender: AppMockRenderer; + + beforeEach(() => { + appMockRender = createAppMockRenderer(); + + jest.clearAllMocks(); + }); + + it('returns a name and a render function', async () => { + const label = 'MockLabel'; + + expect(getEuiTableColumn({ label })).toEqual({ + name: label, + render: expect.any(Function), + width: '250px', + 'data-test-subj': 'text-custom-field-column', + }); + }); + + it('render function renders a text column correctly', async () => { + const key = 'test_key_1'; + const value = 'foobar'; + const column = getEuiTableColumn({ label: 'MockLabel' }); + + appMockRender.render(
{column.render({ key, type: CustomFieldTypes.TEXT, value })}
); + + expect(screen.getByTestId(`text-custom-field-column-view-${key}`)).toBeInTheDocument(); + expect(screen.getByTestId(`text-custom-field-column-view-${key}`)).toHaveTextContent(value); + }); +}); diff --git a/x-pack/plugins/cases/public/components/custom_fields/text/get_eui_table_column.tsx b/x-pack/plugins/cases/public/components/custom_fields/text/get_eui_table_column.tsx new file mode 100644 index 0000000000000..ceef3b821d356 --- /dev/null +++ b/x-pack/plugins/cases/public/components/custom_fields/text/get_eui_table_column.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 from 'react'; + +import type { CaseCustomField } from '../../../../common/types/domain'; +import type { CustomFieldEuiTableColumn } from '../types'; + +export const getEuiTableColumn = ({ label }: { label: string }): CustomFieldEuiTableColumn => ({ + name: label, + width: '250px', + render: (customField: CaseCustomField) => ( +

+ {customField.value} +

+ ), + 'data-test-subj': 'text-custom-field-column', +}); diff --git a/x-pack/plugins/cases/public/components/custom_fields/toggle/configure_text_field.test.ts b/x-pack/plugins/cases/public/components/custom_fields/toggle/configure_text_field.test.ts index c32dac659adfe..2cebda62800a3 100644 --- a/x-pack/plugins/cases/public/components/custom_fields/toggle/configure_text_field.test.ts +++ b/x-pack/plugins/cases/public/components/custom_fields/toggle/configure_text_field.test.ts @@ -18,6 +18,7 @@ describe('configureToggleCustomFieldFactory ', () => { expect(builder).toEqual({ id: 'toggle', label: 'Toggle', + getEuiTableColumn: expect.any(Function), build: expect.any(Function), }); }); diff --git a/x-pack/plugins/cases/public/components/custom_fields/toggle/configure_toggle_field.ts b/x-pack/plugins/cases/public/components/custom_fields/toggle/configure_toggle_field.ts index 00f103fcfdd6a..5076cff23a21a 100644 --- a/x-pack/plugins/cases/public/components/custom_fields/toggle/configure_toggle_field.ts +++ b/x-pack/plugins/cases/public/components/custom_fields/toggle/configure_toggle_field.ts @@ -7,8 +7,10 @@ import type { CustomFieldFactory } from '../types'; import type { CaseCustomFieldToggle } from '../../../../common/types/domain'; + import { CustomFieldTypes } from '../../../../common/types/domain'; import * as i18n from '../translations'; +import { getEuiTableColumn } from './get_eui_table_column'; import { Edit } from './edit'; import { View } from './view'; import { Configure } from './configure'; @@ -17,6 +19,7 @@ import { Create } from './create'; export const configureToggleCustomFieldFactory: CustomFieldFactory = () => ({ id: CustomFieldTypes.TOGGLE, label: i18n.TOGGLE_LABEL, + getEuiTableColumn, build: () => ({ Configure, Edit, diff --git a/x-pack/plugins/cases/public/components/custom_fields/toggle/get_eui_table_column.test.tsx b/x-pack/plugins/cases/public/components/custom_fields/toggle/get_eui_table_column.test.tsx new file mode 100644 index 0000000000000..157159342bee2 --- /dev/null +++ b/x-pack/plugins/cases/public/components/custom_fields/toggle/get_eui_table_column.test.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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import React from 'react'; + +import { screen } from '@testing-library/react'; + +import { CustomFieldTypes } from '../../../../common/types/domain'; +import type { AppMockRenderer } from '../../../common/mock'; +import { createAppMockRenderer } from '../../../common/mock'; +import { getEuiTableColumn } from './get_eui_table_column'; + +describe('getEuiTableColumn ', () => { + let appMockRender: AppMockRenderer; + const key = 'test_key_1'; + + beforeEach(() => { + appMockRender = createAppMockRenderer(); + jest.clearAllMocks(); + }); + + it('returns a name and a render function', async () => { + const label = 'MockLabel'; + + expect(getEuiTableColumn({ label })).toEqual({ + name: label, + render: expect.any(Function), + width: '100px', + 'data-test-subj': 'toggle-custom-field-column', + }); + }); + + it.each([ + ['true', 'check', { key, type: CustomFieldTypes.TOGGLE as const, value: true }], + ['false', 'cross', { key, type: CustomFieldTypes.TOGGLE as const, value: false }], + ['null', 'cross', { key, type: CustomFieldTypes.TOGGLE as const, value: null }], + ])( + 'render function renders a toggle column with value %s correctly', + async (_, expectedResult, customField) => { + const label = 'MockLabel'; + const column = getEuiTableColumn({ label }); + + appMockRender.render(
{column.render(customField)}
); + + expect( + screen.getByTestId(`toggle-custom-field-column-view-${key}-${expectedResult}`) + ).toBeInTheDocument(); + } + ); +}); diff --git a/x-pack/plugins/cases/public/components/custom_fields/toggle/get_eui_table_column.tsx b/x-pack/plugins/cases/public/components/custom_fields/toggle/get_eui_table_column.tsx new file mode 100644 index 0000000000000..b60c034cdd8e9 --- /dev/null +++ b/x-pack/plugins/cases/public/components/custom_fields/toggle/get_eui_table_column.tsx @@ -0,0 +1,27 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; + +import { EuiIcon } from '@elastic/eui'; + +import type { CaseCustomField } from '../../../../common/types/domain'; +import type { CustomFieldEuiTableColumn } from '../types'; + +export const getEuiTableColumn = ({ label }: { label: string }): CustomFieldEuiTableColumn => ({ + name: label, + width: '100px', + render: (customField: CaseCustomField) => ( + + ), + 'data-test-subj': 'toggle-custom-field-column', +}); diff --git a/x-pack/plugins/cases/public/components/custom_fields/types.ts b/x-pack/plugins/cases/public/components/custom_fields/types.ts index e4cddebe59821..6e87cbb8c6cd0 100644 --- a/x-pack/plugins/cases/public/components/custom_fields/types.ts +++ b/x-pack/plugins/cases/public/components/custom_fields/types.ts @@ -6,8 +6,14 @@ */ import type React from 'react'; -import type { CustomFieldTypes } from '../../../common/types/domain'; -import type { CasesConfigurationUICustomField, CaseUICustomField } from '../../containers/types'; +import type { EuiTableComputedColumnType } from '@elastic/eui'; + +import type { CaseCustomField, CustomFieldTypes } from '../../../common/types/domain'; +import type { + CasesConfigurationUICustomField, + CaseUI, + CaseUICustomField, +} from '../../containers/types'; export interface CustomFieldType { Configure: React.FC; @@ -27,9 +33,17 @@ export interface CustomFieldType { }>; } +export type CustomFieldEuiTableColumn = Pick< + EuiTableComputedColumnType, + 'name' | 'width' | 'data-test-subj' +> & { + render: (customField: CaseCustomField) => React.ReactNode; +}; + export type CustomFieldFactory = () => { id: string; label: string; + getEuiTableColumn: (params: { label: string }) => CustomFieldEuiTableColumn; build: () => CustomFieldType; }; diff --git a/x-pack/plugins/cases/public/components/empty_value/empty_value.test.tsx b/x-pack/plugins/cases/public/components/empty_value/empty_value.test.tsx index 47e6ec259640c..04863cc558bed 100644 --- a/x-pack/plugins/cases/public/components/empty_value/empty_value.test.tsx +++ b/x-pack/plugins/cases/public/components/empty_value/empty_value.test.tsx @@ -14,7 +14,7 @@ import { defaultToEmptyTag, getEmptyString, getEmptyStringTag, - getEmptyTagValue, + getEmptyCellValue, getEmptyValue, getOrEmptyTag, } from '.'; @@ -43,10 +43,10 @@ describe('EmptyValue', () => { }); }); - describe('#getEmptyTagValue', () => { + describe('#getEmptyCellValue', () => { const wrapper = mount( -

{getEmptyTagValue()}

+

{getEmptyCellValue()}

); test('should return an empty tag value', () => expect(wrapper.text()).toBe('—')); diff --git a/x-pack/plugins/cases/public/components/empty_value/index.tsx b/x-pack/plugins/cases/public/components/empty_value/index.tsx index 86efb4a78277a..c11ac37a304e7 100644 --- a/x-pack/plugins/cases/public/components/empty_value/index.tsx +++ b/x-pack/plugins/cases/public/components/empty_value/index.tsx @@ -20,12 +20,12 @@ EmptyWrapper.displayName = 'EmptyWrapper'; export const getEmptyValue = () => '—'; export const getEmptyString = () => `(${i18n.EMPTY_STRING})`; -export const getEmptyTagValue = () => {getEmptyValue()}; +export const getEmptyCellValue = () => {getEmptyValue()}; export const getEmptyStringTag = () => {getEmptyString()}; export const defaultToEmptyTag = (item: T): JSX.Element => { if (item == null) { - return getEmptyTagValue(); + return getEmptyCellValue(); } else if (isString(item) && item === '') { return getEmptyStringTag(); } else { @@ -40,7 +40,7 @@ export const getOrEmptyTag = (path: string, item: unknown): JSX.Element => { export const getOrEmptyTagFromValue = (value: string | number | null | undefined): JSX.Element => { if (value == null) { - return getEmptyTagValue(); + return getEmptyCellValue(); } else if (value === '') { return getEmptyStringTag(); } else { diff --git a/x-pack/plugins/cases/server/client/cases/client.ts b/x-pack/plugins/cases/server/client/cases/client.ts index 4a3ed9e6c4b05..2c19df9b4c0f1 100644 --- a/x-pack/plugins/cases/server/client/cases/client.ts +++ b/x-pack/plugins/cases/server/client/cases/client.ts @@ -8,7 +8,6 @@ import type { Case, Cases, User } from '../../../common/types/domain'; import type { CasePostRequest, - CasesFindRequest, CasesFindResponse, CaseResolveResponse, CasesBulkGetRequest, @@ -20,6 +19,7 @@ import type { CasesBulkGetResponse, BulkCreateCasesRequest, BulkCreateCasesResponse, + CasesSearchRequest, } from '../../../common/types/api'; import type { CasesClient } from '../client'; import type { CasesClientInternal } from '../client_internal'; @@ -27,7 +27,7 @@ import type { CasesClientArgs } from '../types'; import { bulkGet } from './bulk_get'; import { create } from './create'; import { deleteCases } from './delete'; -import { find } from './find'; +import { search } from './search'; import type { CasesByAlertIDParams, GetParams } from './get'; import { get, resolve, getCasesByAlertID, getReporters, getTags, getCategories } from './get'; import type { PushParams } from './push'; @@ -52,7 +52,7 @@ export interface CasesSubClient { * * If the `owner` field is left empty then all the cases that the user has access to will be returned. */ - find(params: CasesFindRequest): Promise; + search(params: CasesSearchRequest): Promise; /** * Retrieves a single case with the specified ID. */ @@ -111,7 +111,7 @@ export const createCasesSubClient = ( const casesSubClient: CasesSubClient = { create: (data: CasePostRequest) => create(data, clientArgs, casesClient), bulkCreate: (data: BulkCreateCasesRequest) => bulkCreate(data, clientArgs, casesClient), - find: (params: CasesFindRequest) => find(params, clientArgs), + search: (params: CasesSearchRequest) => search(params, clientArgs, casesClient), get: (params: GetParams) => get(params, clientArgs), resolve: (params: GetParams) => resolve(params, clientArgs), bulkGet: (params) => bulkGet(params, clientArgs), diff --git a/x-pack/plugins/cases/server/client/cases/find.test.ts b/x-pack/plugins/cases/server/client/cases/find.test.ts deleted file mode 100644 index 8acb91b40c383..0000000000000 --- a/x-pack/plugins/cases/server/client/cases/find.test.ts +++ /dev/null @@ -1,184 +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 { v1 as uuidv1 } from 'uuid'; - -import type { Case } from '../../../common/types/domain'; - -import { - MAX_ASSIGNEES_FILTER_LENGTH, - MAX_CASES_PER_PAGE, - MAX_CATEGORY_FILTER_LENGTH, - MAX_DOCS_PER_PAGE, - MAX_REPORTERS_FILTER_LENGTH, - MAX_TAGS_FILTER_LENGTH, -} from '../../../common/constants'; -import { flattenCaseSavedObject } from '../../common/utils'; -import { mockCases } from '../../mocks'; -import { createCasesClientMockArgs, createCasesClientMockFindRequest } from '../mocks'; -import { find } from './find'; - -describe('find', () => { - describe('constructSearch', () => { - const clientArgs = createCasesClientMockArgs(); - const casesMap = new Map( - mockCases.map((obj) => { - return [obj.id, flattenCaseSavedObject({ savedObject: obj, totalComment: 2 })]; - }) - ); - clientArgs.services.caseService.findCasesGroupedByID.mockResolvedValue({ - page: 1, - perPage: 10, - total: casesMap.size, - casesMap, - }); - clientArgs.services.caseService.getCaseStatusStats.mockResolvedValue({ - open: 1, - 'in-progress': 2, - closed: 3, - }); - - afterEach(() => { - jest.clearAllMocks(); - }); - - it('search by uuid updates search term and adds rootSearchFields', async () => { - const search = uuidv1(); - const findRequest = createCasesClientMockFindRequest({ search }); - - await find(findRequest, clientArgs); - await expect(clientArgs.services.caseService.findCasesGroupedByID).toHaveBeenCalled(); - - const call = clientArgs.services.caseService.findCasesGroupedByID.mock.calls[0][0]; - - expect(call.caseOptions.search).toBe(`"${search}" "cases:${search}"`); - expect(call.caseOptions).toHaveProperty('rootSearchFields', ['_id']); - }); - - it('regular search term does not cause rootSearchFields to be appended', async () => { - const search = 'foobar'; - const findRequest = createCasesClientMockFindRequest({ search }); - await find(findRequest, clientArgs); - await expect(clientArgs.services.caseService.findCasesGroupedByID).toHaveBeenCalled(); - - const call = clientArgs.services.caseService.findCasesGroupedByID.mock.calls[0][0]; - - expect(call.caseOptions.search).toBe(search); - expect(call.caseOptions).not.toHaveProperty('rootSearchFields'); - }); - }); - - describe('errors', () => { - const clientArgs = createCasesClientMockArgs(); - - beforeEach(() => { - jest.clearAllMocks(); - }); - - it('when foo:bar attribute in request payload', async () => { - const search = 'sample_text'; - const findRequest = createCasesClientMockFindRequest({ search }); - await expect( - // @ts-expect-error foo is an invalid field - find({ ...findRequest, foo: 'bar' }, clientArgs) - ).rejects.toThrowErrorMatchingInlineSnapshot( - `"Failed to find cases: {\\"search\\":\\"sample_text\\",\\"searchFields\\":[\\"title\\",\\"description\\"],\\"severity\\":\\"low\\",\\"assignees\\":[],\\"reporters\\":[],\\"status\\":\\"open\\",\\"tags\\":[],\\"owner\\":[],\\"sortField\\":\\"createdAt\\",\\"sortOrder\\":\\"desc\\",\\"foo\\":\\"bar\\"}: Error: invalid keys \\"foo\\""` - ); - }); - - it('invalid searchFields with array', async () => { - const searchFields = ['foobar']; - - // @ts-expect-error - const findRequest = createCasesClientMockFindRequest({ searchFields }); - - await expect(find(findRequest, clientArgs)).rejects.toThrow( - 'Error: Invalid value "foobar" supplied to "searchFields"' - ); - }); - - it('invalid searchFields with single string', async () => { - const searchFields = 'foobar'; - - // @ts-expect-error - const findRequest = createCasesClientMockFindRequest({ searchFields }); - - await expect(find(findRequest, clientArgs)).rejects.toThrow( - 'Error: Invalid value "foobar" supplied to "searchFields"' - ); - }); - - it('invalid sortField', async () => { - const sortField = 'foobar'; - - // @ts-expect-error - const findRequest = createCasesClientMockFindRequest({ sortField }); - - await expect(find(findRequest, clientArgs)).rejects.toThrow( - 'Error: Invalid value "foobar" supplied to "sortField"' - ); - }); - - it(`throws an error when the category array has ${MAX_CATEGORY_FILTER_LENGTH} items`, async () => { - const category = Array(MAX_CATEGORY_FILTER_LENGTH + 1).fill('foobar'); - - const findRequest = createCasesClientMockFindRequest({ category }); - - await expect(find(findRequest, clientArgs)).rejects.toThrow( - `Error: The length of the field category is too long. Array must be of length <= ${MAX_CATEGORY_FILTER_LENGTH}` - ); - }); - - it(`throws an error when the tags array has ${MAX_TAGS_FILTER_LENGTH} items`, async () => { - const tags = Array(MAX_TAGS_FILTER_LENGTH + 1).fill('foobar'); - - const findRequest = createCasesClientMockFindRequest({ tags }); - - await expect(find(findRequest, clientArgs)).rejects.toThrowError( - `Error: The length of the field tags is too long. Array must be of length <= ${MAX_TAGS_FILTER_LENGTH}` - ); - }); - - it(`throws an error when the assignees array has ${MAX_ASSIGNEES_FILTER_LENGTH} items`, async () => { - const assignees = Array(MAX_ASSIGNEES_FILTER_LENGTH + 1).fill('foobar'); - - const findRequest = createCasesClientMockFindRequest({ assignees }); - - await expect(find(findRequest, clientArgs)).rejects.toThrowError( - `Error: The length of the field assignees is too long. Array must be of length <= ${MAX_ASSIGNEES_FILTER_LENGTH}` - ); - }); - - it(`throws an error when the reporters array has ${MAX_REPORTERS_FILTER_LENGTH} items`, async () => { - const reporters = Array(MAX_REPORTERS_FILTER_LENGTH + 1).fill('foobar'); - - const findRequest = createCasesClientMockFindRequest({ reporters }); - - await expect(find(findRequest, clientArgs)).rejects.toThrowError( - `Error: The length of the field reporters is too long. Array must be of length <= ${MAX_REPORTERS_FILTER_LENGTH}.` - ); - }); - - it('Invalid total items results in error', async () => { - const findRequest = createCasesClientMockFindRequest({ page: 209, perPage: 100 }); - - await expect(find(findRequest, clientArgs)).rejects.toThrowError( - `Error: The number of documents is too high. Paginating through more than ${MAX_DOCS_PER_PAGE} documents is not possible.` - ); - }); - - it('Invalid perPage items results in error', async () => { - const findRequest = createCasesClientMockFindRequest({ - page: 1, - perPage: MAX_CASES_PER_PAGE + 1, - }); - - await expect(find(findRequest, clientArgs)).rejects.toThrowError( - `Error: The provided perPage value is too high. The maximum allowed perPage value is ${MAX_CASES_PER_PAGE}.` - ); - }); - }); -}); diff --git a/x-pack/plugins/cases/server/client/cases/search.test.ts b/x-pack/plugins/cases/server/client/cases/search.test.ts new file mode 100644 index 0000000000000..0bf0eb6d61320 --- /dev/null +++ b/x-pack/plugins/cases/server/client/cases/search.test.ts @@ -0,0 +1,330 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import { v1 as uuidv1 } from 'uuid'; + +import type { Case } from '../../../common/types/domain'; +import { CustomFieldTypes } from '../../../common/types/domain'; + +import { + MAX_ASSIGNEES_FILTER_LENGTH, + MAX_CASES_PER_PAGE, + MAX_CATEGORY_FILTER_LENGTH, + MAX_DOCS_PER_PAGE, + MAX_REPORTERS_FILTER_LENGTH, + MAX_TAGS_FILTER_LENGTH, +} from '../../../common/constants'; +import { flattenCaseSavedObject } from '../../common/utils'; +import { mockCases } from '../../mocks'; +import { + createCasesClientMock, + createCasesClientMockArgs, + createCasesClientMockSearchRequest, +} from '../mocks'; +import { search } from './search'; + +describe('search', () => { + const configureMock = [ + { + customFields: [ + { + key: 'first_key', + type: CustomFieldTypes.TEXT, + label: 'Text field', + required: true, + }, + { + key: 'second_key', + type: CustomFieldTypes.TOGGLE, + label: 'Toggle field', + required: true, + }, + { + key: 'third_key', + type: CustomFieldTypes.TOGGLE, + label: 'another toggle field', + required: false, + }, + ], + }, + ]; + const casesClientMock = createCasesClientMock(); + casesClientMock.configure.get = jest.fn().mockResolvedValue(configureMock); + + describe('constructSearch', () => { + const clientArgs = createCasesClientMockArgs(); + const casesMap = new Map( + mockCases.map((obj) => { + return [obj.id, flattenCaseSavedObject({ savedObject: obj, totalComment: 2 })]; + }) + ); + clientArgs.services.caseService.findCasesGroupedByID.mockResolvedValue({ + page: 1, + perPage: 10, + total: casesMap.size, + casesMap, + }); + clientArgs.services.caseService.getCaseStatusStats.mockResolvedValue({ + open: 1, + 'in-progress': 2, + closed: 3, + }); + + afterEach(() => { + jest.clearAllMocks(); + }); + + it('search by uuid updates search term and adds rootSearchFields', async () => { + const searchId = uuidv1(); + const findRequest = createCasesClientMockSearchRequest({ search: searchId }); + + await search(findRequest, clientArgs, casesClientMock); + await expect(clientArgs.services.caseService.findCasesGroupedByID).toHaveBeenCalled(); + + const call = clientArgs.services.caseService.findCasesGroupedByID.mock.calls[0][0]; + + expect(call.caseOptions.search).toBe(`"${searchId}" "cases:${searchId}"`); + expect(call.caseOptions).toHaveProperty('rootSearchFields', ['_id']); + }); + + it('regular search term does not cause rootSearchFields to be appended', async () => { + const searchTerm = 'foobar'; + const findRequest = createCasesClientMockSearchRequest({ search: searchTerm }); + await search(findRequest, clientArgs, casesClientMock); + await expect(clientArgs.services.caseService.findCasesGroupedByID).toHaveBeenCalled(); + + const call = clientArgs.services.caseService.findCasesGroupedByID.mock.calls[0][0]; + + expect(call.caseOptions.search).toBe(searchTerm); + expect(call.caseOptions).not.toHaveProperty('rootSearchFields'); + }); + + it('search with single custom field', async () => { + const findRequest = createCasesClientMockSearchRequest({ + customFields: { second_key: [true] }, + owner: 'cases', + }); + await search(findRequest, clientArgs, casesClientMock); + await expect(clientArgs.services.caseService.findCasesGroupedByID).toHaveBeenCalled(); + }); + + it('search with single custom field with multiple values', async () => { + const findRequest = createCasesClientMockSearchRequest({ + customFields: { second_key: [true, null] }, + owner: ['cases'], + }); + await search(findRequest, clientArgs, casesClientMock); + await expect(clientArgs.services.caseService.findCasesGroupedByID).toHaveBeenCalled(); + }); + + it('search with multiple custom fields', async () => { + const findRequest = createCasesClientMockSearchRequest({ + customFields: { second_key: [true], third_key: [true] }, + owner: ['cases'], + }); + await search(findRequest, clientArgs, casesClientMock); + await expect(clientArgs.services.caseService.findCasesGroupedByID).toHaveBeenCalled(); + }); + + it('search with null custom fields', async () => { + const findRequest = createCasesClientMockSearchRequest({ + customFields: { second_key: [null] }, + owner: 'cases', + }); + await search(findRequest, clientArgs, casesClientMock); + await expect(clientArgs.services.caseService.findCasesGroupedByID).toHaveBeenCalled(); + }); + }); + + describe('errors', () => { + const clientArgs = createCasesClientMockArgs(); + casesClientMock.configure.get = jest.fn().mockResolvedValue(configureMock); + + beforeEach(() => { + jest.clearAllMocks(); + }); + + it('when foo:bar attribute in request payload', async () => { + const searchTerm = 'sample_text'; + const findRequest = createCasesClientMockSearchRequest({ search: searchTerm }); + await expect( + // @ts-expect-error foo is an invalid field + search({ ...findRequest, foo: 'bar' }, clientArgs) + ).rejects.toThrowErrorMatchingInlineSnapshot( + `"Failed to find cases: {\\"search\\":\\"sample_text\\",\\"searchFields\\":[\\"title\\",\\"description\\"],\\"severity\\":\\"low\\",\\"assignees\\":[],\\"reporters\\":[],\\"status\\":\\"open\\",\\"tags\\":[],\\"owner\\":[],\\"sortField\\":\\"createdAt\\",\\"sortOrder\\":\\"desc\\",\\"customFields\\":{},\\"foo\\":\\"bar\\"}: Error: invalid keys \\"foo\\""` + ); + }); + + it('invalid searchFields with array', async () => { + const searchFields = ['foobar']; + + // @ts-expect-error + const findRequest = createCasesClientMockSearchRequest({ searchFields }); + + await expect(search(findRequest, clientArgs, casesClientMock)).rejects.toThrow( + 'Error: Invalid value "foobar" supplied to "searchFields"' + ); + }); + + it('invalid searchFields with single string', async () => { + const searchFields = 'foobar'; + + // @ts-expect-error + const findRequest = createCasesClientMockSearchRequest({ searchFields }); + + await expect(search(findRequest, clientArgs, casesClientMock)).rejects.toThrow( + 'Error: Invalid value "foobar" supplied to "searchFields"' + ); + }); + + it('invalid sortField', async () => { + const sortField = 'foobar'; + + // @ts-expect-error + const findRequest = createCasesClientMockSearchRequest({ sortField }); + + await expect(search(findRequest, clientArgs, casesClientMock)).rejects.toThrow( + 'Error: Invalid value "foobar" supplied to "sortField"' + ); + }); + + it(`throws an error when the category array has ${MAX_CATEGORY_FILTER_LENGTH} items`, async () => { + const category = Array(MAX_CATEGORY_FILTER_LENGTH + 1).fill('foobar'); + + const findRequest = createCasesClientMockSearchRequest({ category }); + + await expect(search(findRequest, clientArgs, casesClientMock)).rejects.toThrow( + `Error: The length of the field category is too long. Array must be of length <= ${MAX_CATEGORY_FILTER_LENGTH}` + ); + }); + + it(`throws an error when the tags array has ${MAX_TAGS_FILTER_LENGTH} items`, async () => { + const tags = Array(MAX_TAGS_FILTER_LENGTH + 1).fill('foobar'); + + const findRequest = createCasesClientMockSearchRequest({ tags }); + + await expect(search(findRequest, clientArgs, casesClientMock)).rejects.toThrowError( + `Error: The length of the field tags is too long. Array must be of length <= ${MAX_TAGS_FILTER_LENGTH}` + ); + }); + + it(`throws an error when the assignees array has ${MAX_ASSIGNEES_FILTER_LENGTH} items`, async () => { + const assignees = Array(MAX_ASSIGNEES_FILTER_LENGTH + 1).fill('foobar'); + + const findRequest = createCasesClientMockSearchRequest({ assignees }); + + await expect(search(findRequest, clientArgs, casesClientMock)).rejects.toThrowError( + `Error: The length of the field assignees is too long. Array must be of length <= ${MAX_ASSIGNEES_FILTER_LENGTH}` + ); + }); + + it(`throws an error when the reporters array has ${MAX_REPORTERS_FILTER_LENGTH} items`, async () => { + const reporters = Array(MAX_REPORTERS_FILTER_LENGTH + 1).fill('foobar'); + + const findRequest = createCasesClientMockSearchRequest({ reporters }); + + await expect(search(findRequest, clientArgs, casesClientMock)).rejects.toThrowError( + `Error: The length of the field reporters is too long. Array must be of length <= ${MAX_REPORTERS_FILTER_LENGTH}.` + ); + }); + + it('Invalid total items results in error', async () => { + const findRequest = createCasesClientMockSearchRequest({ page: 209, perPage: 100 }); + + await expect(search(findRequest, clientArgs, casesClientMock)).rejects.toThrowError( + `Error: The number of documents is too high. Paginating through more than ${MAX_DOCS_PER_PAGE} documents is not possible.` + ); + }); + + it('Invalid perPage items results in error', async () => { + const findRequest = createCasesClientMockSearchRequest({ + page: 1, + perPage: MAX_CASES_PER_PAGE + 1, + }); + + await expect(search(findRequest, clientArgs, casesClientMock)).rejects.toThrowError( + `Error: The provided perPage value is too high. The maximum allowed perPage value is ${MAX_CASES_PER_PAGE}.` + ); + }); + + it('throws error when search with customFields and no owner', async () => { + const findRequest = createCasesClientMockSearchRequest({ + customFields: { second_key: [true] }, + }); + + await expect(search(findRequest, clientArgs, casesClientMock)).rejects.toThrowError( + ` Error: Owner must be provided. Multiple owners are not supported.` + ); + }); + + it('throws error when search with customFields and owner as empty string array', async () => { + const findRequest = createCasesClientMockSearchRequest({ + customFields: { second_key: [true] }, + owner: [''], + }); + + await expect(search(findRequest, clientArgs, casesClientMock)).rejects.toThrowError( + ` Error: Owner must be provided. Multiple owners are not supported.` + ); + }); + + it('throws error when search with customFields and multiple owners', async () => { + const findRequest = createCasesClientMockSearchRequest({ + customFields: { second_key: [true] }, + owner: ['cases', 'observability'], + }); + + await expect(search(findRequest, clientArgs, casesClientMock)).rejects.toThrowError( + ` Error: Owner must be provided. Multiple owners are not supported.` + ); + }); + + it('throws error when no customField is not same as configuration', async () => { + const findRequest = createCasesClientMockSearchRequest({ + customFields: { test_custom_field_key: [true] }, + owner: 'cases', + }); + + await expect(search(findRequest, clientArgs, casesClientMock)).rejects.toThrowError( + ` Error: Invalid custom field key: test_custom_field_key.` + ); + }); + + it('throws error when search with non filterable custom field', async () => { + const findRequest = createCasesClientMockSearchRequest({ + customFields: { first_key: ['hello'] }, + owner: 'cases', + }); + + await expect(search(findRequest, clientArgs, casesClientMock)).rejects.toThrowError( + ` Error: Filtering by custom field of type text is not allowed.` + ); + }); + + it('throws error when search with invalid value', async () => { + const findRequest = createCasesClientMockSearchRequest({ + customFields: { second_key: ['hello'] }, + owner: 'cases', + }); + + await expect(search(findRequest, clientArgs, casesClientMock)).rejects.toThrowError( + ` Error: Unsupported filtering value for custom field of type toggle.` + ); + }); + + it('throws error when no customFields in configuration', async () => { + casesClientMock.configure.get = jest.fn().mockResolvedValue([]); + const findRequest = createCasesClientMockSearchRequest({ + customFields: { second_key: [true] }, + owner: 'cases', + }); + + await expect(search(findRequest, clientArgs, casesClientMock)).rejects.toThrowError( + ` Error: No custom fields configured.` + ); + }); + }); +}); diff --git a/x-pack/plugins/cases/server/client/cases/find.ts b/x-pack/plugins/cases/server/client/cases/search.ts similarity index 51% rename from x-pack/plugins/cases/server/client/cases/find.ts rename to x-pack/plugins/cases/server/client/cases/search.ts index c61c4ba71ffde..554f0c8055aaa 100644 --- a/x-pack/plugins/cases/server/client/cases/find.ts +++ b/x-pack/plugins/cases/server/client/cases/search.ts @@ -5,30 +5,33 @@ * 2.0. */ -import { isEmpty } from 'lodash'; +import { isEmpty, isArray } from 'lodash'; import Boom from '@hapi/boom'; -import type { CasesFindRequest, CasesFindResponse } from '../../../common/types/api'; -import { CasesFindRequestRt, CasesFindResponseRt } from '../../../common/types/api'; +import type { CustomFieldsConfiguration } from '../../../common/types/domain'; +import type { CasesSearchRequest, CasesFindResponse } from '../../../common/types/api'; +import { CasesSearchRequestRt, CasesFindResponseRt } from '../../../common/types/api'; import { decodeWithExcessOrThrow } from '../../../common/api'; import { createCaseError } from '../../common/error'; import { asArray, transformCases } from '../../common/utils'; import { constructQueryOptions, constructSearch } from '../utils'; import { Operations } from '../../authorization'; -import type { CasesClientArgs } from '..'; +import type { CasesClient, CasesClientArgs } from '..'; import { LICENSING_CASE_ASSIGNMENT_FEATURE } from '../../common/constants'; -import type { CasesFindQueryParams } from '../types'; +import type { CasesSearchParams } from '../types'; import { decodeOrThrow } from '../../../common/api/runtime_types'; +import { validateSearchCasesCustomFields } from './validators'; /** * Retrieves a case and optionally its comments. * * @ignore */ -export const find = async ( - params: CasesFindRequest, - clientArgs: CasesClientArgs +export const search = async ( + params: CasesSearchRequest, + clientArgs: CasesClientArgs, + casesClient: CasesClient ): Promise => { const { services: { caseService, licensingService }, @@ -39,13 +42,18 @@ export const find = async ( } = clientArgs; try { - const queryParams = decodeWithExcessOrThrow(CasesFindRequestRt)(params); + const paramArgs = decodeWithExcessOrThrow(CasesSearchRequestRt)(params); + const configArgs = paramArgs.owner ? { owner: paramArgs.owner } : {}; + const configurations = await casesClient.configure.get(configArgs); + const customFieldsConfiguration: CustomFieldsConfiguration = configurations + .map((config) => config.customFields) + .flat(); /** * Assign users to a case is only available to Platinum+ */ - if (!isEmpty(queryParams.assignees)) { + if (!isEmpty(paramArgs.assignees)) { const hasPlatinumLicenseOrGreater = await licensingService.isAtLeastPlatinum(); if (!hasPlatinumLicenseOrGreater) { @@ -57,39 +65,67 @@ export const find = async ( licensingService.notifyUsage(LICENSING_CASE_ASSIGNMENT_FEATURE); } + /** + * Validate custom fields + */ + if (paramArgs?.customFields && !isEmpty(paramArgs?.customFields)) { + /** + * throw error if params has customFields and no owner + */ + + const isValidArray = + isArray(paramArgs.owner) && + (!paramArgs.owner.length || paramArgs.owner.length > 1 || isEmpty(paramArgs.owner[0])); + + if (!paramArgs.owner || isValidArray) { + throw Boom.badRequest('Owner must be provided. Multiple owners are not supported.'); + } + + validateSearchCasesCustomFields({ + customFieldsConfiguration, + customFields: paramArgs.customFields, + }); + } + const { filter: authorizationFilter, ensureSavedObjectsAreAuthorized } = await authorization.getAuthorizationFilter(Operations.findCases); - const queryArgs: CasesFindQueryParams = { - tags: queryParams.tags, - reporters: queryParams.reporters, - sortField: queryParams.sortField, - status: queryParams.status, - severity: queryParams.severity, - owner: queryParams.owner, - from: queryParams.from, - to: queryParams.to, - assignees: queryParams.assignees, - category: queryParams.category, + const options: CasesSearchParams = { + tags: paramArgs.tags, + reporters: paramArgs.reporters, + sortField: paramArgs.sortField, + status: paramArgs.status, + severity: paramArgs.severity, + owner: paramArgs.owner, + from: paramArgs.from, + to: paramArgs.to, + assignees: paramArgs.assignees, + category: paramArgs.category, + customFields: paramArgs.customFields, }; const statusStatsOptions = constructQueryOptions({ - ...queryArgs, + ...options, status: undefined, + customFieldsConfiguration, authorizationFilter, }); - const caseQueryOptions = constructQueryOptions({ ...queryArgs, authorizationFilter }); + const caseQueryOptions = constructQueryOptions({ + ...options, + customFieldsConfiguration, + authorizationFilter, + }); - const caseSearch = constructSearch(queryParams.search, spaceId, savedObjectsSerializer); + const caseSearch = constructSearch(paramArgs.search, spaceId, savedObjectsSerializer); const [cases, statusStats] = await Promise.all([ caseService.findCasesGroupedByID({ caseOptions: { - ...queryParams, + ...paramArgs, ...caseQueryOptions, ...caseSearch, - searchFields: asArray(queryParams.searchFields), + searchFields: asArray(paramArgs.searchFields), }, }), caseService.getCaseStatusStats({ diff --git a/x-pack/plugins/cases/server/client/cases/validators.test.ts b/x-pack/plugins/cases/server/client/cases/validators.test.ts index 888852e6f90ed..abc4c27385b02 100644 --- a/x-pack/plugins/cases/server/client/cases/validators.test.ts +++ b/x-pack/plugins/cases/server/client/cases/validators.test.ts @@ -7,10 +7,13 @@ import type { CustomFieldsConfiguration, CaseCustomFields } from '../../../common/types/domain'; import { CustomFieldTypes } from '../../../common/types/domain'; +import type { CasesSearchRequest } from '../../../common/types/api'; +import { MAX_CUSTOM_FIELDS_PER_CASE } from '../../../common/constants'; import { validateCustomFieldKeysAgainstConfiguration, validateCustomFieldTypesInRequest, validateRequiredCustomFields, + validateSearchCasesCustomFields, } from './validators'; describe('validators', () => { @@ -440,4 +443,134 @@ describe('validators', () => { ); }); }); + + describe('validateSearchCasesCustomFields', () => { + beforeEach(() => { + jest.clearAllMocks(); + }); + + const customFieldsConfiguration: CustomFieldsConfiguration = [ + { + key: 'first_key', + type: CustomFieldTypes.TEXT, + label: 'Text field', + required: true, + }, + { + key: 'second_key', + type: CustomFieldTypes.TOGGLE, + label: 'Toggle field', + required: true, + }, + ]; + + const customFields: CasesSearchRequest['customFields'] = { + second_key: [true], + }; + + it('does not throw when custom fields are correct', () => { + const newConfig = [ + ...customFieldsConfiguration, + { + key: 'third_key', + type: CustomFieldTypes.TOGGLE, + label: 'Another toggle field', + required: false, + }, + ]; + + const newCustomFields = { ...customFields, third_key: [false] }; + + expect(() => + validateSearchCasesCustomFields({ + customFieldsConfiguration: newConfig, + customFields: newCustomFields, + }) + ).not.toThrow(); + }); + + it('does not throw when multiple custom fields', () => { + expect(() => + validateSearchCasesCustomFields({ + customFieldsConfiguration, + customFields, + }) + ).not.toThrow(); + }); + + it('does not throw when custom fields are empty', () => { + expect(() => + validateSearchCasesCustomFields({ + customFieldsConfiguration, + customFields: {}, + }) + ).not.toThrow(); + }); + + it('does not throw when custom field value is null', () => { + expect(() => + validateSearchCasesCustomFields({ + customFieldsConfiguration, + customFields: { second_key: [null] }, + }) + ).not.toThrow(); + }); + + it('throws error when custom fields configurations is empty', () => { + expect(() => + validateSearchCasesCustomFields({ + customFieldsConfiguration: [], + customFields, + }) + ).toThrowErrorMatchingInlineSnapshot(`"No custom fields configured."`); + }); + + it('throws error when custom fields key does not match with configuration', () => { + expect(() => + validateSearchCasesCustomFields({ + customFieldsConfiguration, + customFields: { random_key: [true] }, + }) + ).toThrowErrorMatchingInlineSnapshot(`"Invalid custom field key: random_key."`); + }); + + it('throws error when custom field is not filterable', () => { + expect(() => + validateSearchCasesCustomFields({ + customFieldsConfiguration, + customFields: { first_key: ['hello'] }, + }) + ).toThrowErrorMatchingInlineSnapshot( + `"Filtering by custom field of type text is not allowed."` + ); + }); + + it('throws error when custom field is searched with invalid value', () => { + expect(() => + validateSearchCasesCustomFields({ + customFieldsConfiguration, + customFields: { second_key: ['foobar', true, 1234] }, + }) + ).toThrowErrorMatchingInlineSnapshot( + `"Unsupported filtering value for custom field of type toggle."` + ); + }); + + it('throws error when custom fields reach maximum', () => { + let customFieldsMax = {}; + + for (let i = 0; i <= MAX_CUSTOM_FIELDS_PER_CASE + 1; i++) { + customFieldsMax = { ...customFieldsMax, [`test_key_${i}`]: [true] }; + } + + expect(() => + validateSearchCasesCustomFields({ + customFieldsConfiguration, + customFields: customFieldsMax, + }) + ).toThrowErrorMatchingInlineSnapshot( + `"Maximum ${MAX_CUSTOM_FIELDS_PER_CASE} customFields are allowed."` + ); + }); + }); }); diff --git a/x-pack/plugins/cases/server/client/cases/validators.ts b/x-pack/plugins/cases/server/client/cases/validators.ts index 7817e6646695a..0d76875be0114 100644 --- a/x-pack/plugins/cases/server/client/cases/validators.ts +++ b/x-pack/plugins/cases/server/client/cases/validators.ts @@ -5,11 +5,14 @@ * 2.0. */ -import { differenceWith, intersectionWith } from 'lodash'; +import { differenceWith, intersectionWith, isEmpty } from 'lodash'; import Boom from '@hapi/boom'; import type { CustomFieldsConfiguration } from '../../../common/types/domain'; -import type { CaseRequestCustomFields } from '../../../common/types/api'; +import type { CaseRequestCustomFields, CasesSearchRequest } from '../../../common/types/api'; import { validateDuplicatedCustomFieldKeysInRequest } from '../validators'; +import type { ICasesCustomField } from '../../custom_fields'; +import { casesCustomFields } from '../../custom_fields'; +import { MAX_CUSTOM_FIELDS_PER_CASE } from '../../../common/constants'; interface CustomFieldValidationParams { requestCustomFields?: CaseRequestCustomFields; @@ -133,3 +136,43 @@ export const validateRequiredCustomFields = ({ ); } }; + +export const validateSearchCasesCustomFields = ({ + customFieldsConfiguration, + customFields, +}: { + customFieldsConfiguration: CustomFieldsConfiguration; + customFields: CasesSearchRequest['customFields']; +}) => { + let customFieldsMapping: ICasesCustomField | null = null; + + if (!customFields || isEmpty(customFields)) { + return; + } + + if (!customFieldsConfiguration.length) { + throw Boom.badRequest('No custom fields configured.'); + } + + if (Object.keys(customFields).length > MAX_CUSTOM_FIELDS_PER_CASE) { + throw Boom.badRequest(`Maximum ${MAX_CUSTOM_FIELDS_PER_CASE} customFields are allowed.`); + } + + Object.entries(customFields).forEach(([key, value]) => { + const customFieldConfig = customFieldsConfiguration.find((config) => config.key === key); + + if (!customFieldConfig) { + throw Boom.badRequest(`Invalid custom field key: ${key}.`); + } + + customFieldsMapping = casesCustomFields.get(customFieldConfig.type); + + if (!customFieldsMapping?.isFilterable) { + throw Boom.badRequest( + `Filtering by custom field of type ${customFieldConfig.type} is not allowed.` + ); + } + + customFieldsMapping?.validateFilteringValues(value); + }); +}; diff --git a/x-pack/plugins/cases/server/client/mocks.ts b/x-pack/plugins/cases/server/client/mocks.ts index 7d4015d15a085..f9d02c094e425 100644 --- a/x-pack/plugins/cases/server/client/mocks.ts +++ b/x-pack/plugins/cases/server/client/mocks.ts @@ -15,7 +15,7 @@ import { actionsClientMock } from '@kbn/actions-plugin/server/actions_client/act import { makeLensEmbeddableFactory } from '@kbn/lens-plugin/server/embeddable/make_lens_embeddable_factory'; import { serializerMock } from '@kbn/core-saved-objects-base-server-mocks'; -import type { CasesFindRequest } from '../../common/types/api'; +import type { CasesSearchRequest } from '../../common/types/api'; import type { CasesClient, CasesClientInternal } from '.'; import type { AttachmentsSubClient } from './attachments/client'; import type { CasesSubClient } from './cases/client'; @@ -48,7 +48,7 @@ const createCasesSubClientMock = (): CasesSubClientMock => { return { create: jest.fn(), bulkCreate: jest.fn(), - find: jest.fn(), + search: jest.fn(), resolve: jest.fn(), get: jest.fn(), bulkGet: jest.fn(), @@ -213,9 +213,9 @@ export const createCasesClientMockArgs = () => { }; }; -export const createCasesClientMockFindRequest = ( - overwrites?: CasesFindRequest -): CasesFindRequest => ({ +export const createCasesClientMockSearchRequest = ( + overwrites?: CasesSearchRequest +): CasesSearchRequest => ({ search: '', searchFields: ['title', 'description'], severity: CaseSeverity.LOW, @@ -226,5 +226,6 @@ export const createCasesClientMockFindRequest = ( owner: [], sortField: SortFieldCase.createdAt, sortOrder: 'desc', + customFields: {}, ...overwrites, }); diff --git a/x-pack/plugins/cases/server/client/types.ts b/x-pack/plugins/cases/server/client/types.ts index 23e35b592efa5..e36b80563e77e 100644 --- a/x-pack/plugins/cases/server/client/types.ts +++ b/x-pack/plugins/cases/server/client/types.ts @@ -14,7 +14,7 @@ import type { IBasePath } from '@kbn/core-http-browser'; import type { ISavedObjectsSerializer } from '@kbn/core-saved-objects-server'; import type { KueryNode } from '@kbn/es-query'; import type { FileServiceStart } from '@kbn/files-plugin/server'; -import type { CasesFindRequest } from '../../common/types/api'; +import type { CasesSearchRequest } from '../../common/types/api'; import type { Authorization } from '../authorization/authorization'; import type { CaseConfigureService, @@ -61,9 +61,9 @@ export interface CasesClientArgs { readonly fileService: FileServiceStart; } -export type CasesFindQueryParams = Partial< +export type CasesSearchParams = Partial< Pick< - CasesFindRequest, + CasesSearchRequest, | 'tags' | 'reporters' | 'status' @@ -74,5 +74,6 @@ export type CasesFindQueryParams = Partial< | 'assignees' | 'category' | 'sortField' + | 'customFields' > & { authorizationFilter?: KueryNode } >; diff --git a/x-pack/plugins/cases/server/client/utils.test.ts b/x-pack/plugins/cases/server/client/utils.test.ts index 1b4ae12a3f429..8fb54f907927e 100644 --- a/x-pack/plugins/cases/server/client/utils.test.ts +++ b/x-pack/plugins/cases/server/client/utils.test.ts @@ -8,7 +8,8 @@ import { v1 as uuidv1 } from 'uuid'; import { DEFAULT_NAMESPACE_STRING } from '@kbn/core-saved-objects-utils-server'; -import { toElasticsearchQuery } from '@kbn/es-query'; +import type { KueryNode } from '@kbn/es-query'; +import { toElasticsearchQuery, toKqlExpression } from '@kbn/es-query'; import { createSavedObjectsSerializerMock } from './mocks'; import { @@ -20,7 +21,8 @@ import { convertSortField, } from './utils'; import { CasePersistedSeverity, CasePersistedStatus } from '../common/types/case'; -import { CaseSeverity, CaseStatuses } from '../../common/types/domain'; +import type { CustomFieldsConfiguration } from '../../common/types/domain'; +import { CaseSeverity, CaseStatuses, CustomFieldTypes } from '../../common/types/domain'; describe('utils', () => { describe('buildFilter', () => { @@ -674,6 +676,162 @@ describe('utils', () => { } `); }); + + describe('customFields', () => { + const customFieldsConfiguration: CustomFieldsConfiguration = [ + { + key: 'first_key', + type: CustomFieldTypes.TEXT, + label: 'Text field', + required: true, + }, + { + key: 'second_key', + type: CustomFieldTypes.TOGGLE, + label: 'Toggle field', + required: true, + }, + { + key: 'third_key', + type: CustomFieldTypes.TOGGLE, + label: 'another toggle field', + required: false, + }, + ]; + + it('creates a filter with toggle customField', () => { + const kqlFilter = toKqlExpression( + constructQueryOptions({ + customFields: { second_key: [true] }, + customFieldsConfiguration, + }).filter as KueryNode + ); + + expect(kqlFilter).toMatchInlineSnapshot( + `"cases.attributes.customFields: { (key: second_key AND value.boolean: true) }"` + ); + }); + + it('creates a filter with text customField', () => { + const kqlFilter = toKqlExpression( + constructQueryOptions({ + customFields: { first_key: ['hello'] }, + customFieldsConfiguration, + }).filter as KueryNode + ); + + expect(kqlFilter).toMatchInlineSnapshot( + `"cases.attributes.customFields: { (key: first_key AND value.string: hello) }"` + ); + }); + + it('creates a filter with null customField value', () => { + const kqlFilter = toKqlExpression( + constructQueryOptions({ + customFields: { first_key: [null] }, + customFieldsConfiguration, + }).filter as KueryNode + ); + + expect(kqlFilter).toMatchInlineSnapshot( + `"cases.attributes.customFields: { (key: first_key AND NOT value: *) }"` + ); + }); + + it('creates a filter with multiple customFields', () => { + const kqlFilter = toKqlExpression( + constructQueryOptions({ + customFields: { second_key: [true], third_key: [false] }, + customFieldsConfiguration, + }).filter as KueryNode + ); + expect(kqlFilter).toMatchInlineSnapshot( + `"(cases.attributes.customFields: { (key: second_key AND value.boolean: true) } AND cases.attributes.customFields: { (key: third_key AND value.boolean: false) })"` + ); + }); + + it('creates a filter with multiple customFields values', () => { + const kqlFilter = toKqlExpression( + constructQueryOptions({ + customFields: { second_key: [true, null], third_key: [false] }, + customFieldsConfiguration, + }).filter as KueryNode + ); + + expect(kqlFilter).toMatchInlineSnapshot( + `"((cases.attributes.customFields: { (key: second_key AND value.boolean: true) } OR cases.attributes.customFields: { (key: second_key AND NOT value: *) }) AND cases.attributes.customFields: { (key: third_key AND value.boolean: false) })"` + ); + }); + + it('creates a filter with only key when value is empty', () => { + const kqlFilter = toKqlExpression( + constructQueryOptions({ + customFields: { second_key: [], third_key: [] }, + customFieldsConfiguration, + }).filter as KueryNode + ); + + expect(kqlFilter).toMatchInlineSnapshot( + `"(cases.attributes.customFields: { key: second_key } AND cases.attributes.customFields: { key: third_key })"` + ); + }); + + it('does not create a filter when customFields is undefined', () => { + expect( + constructQueryOptions({ + customFields: undefined, + customFieldsConfiguration, + }).filter + ).toBeUndefined(); + }); + + it('does not create a filter when customFieldsConfiguration is undefined', () => { + expect( + constructQueryOptions({ + customFields: { second_key: [true] }, + customFieldsConfiguration: undefined, + }).filter + ).toBeUndefined(); + }); + + it('does not create a filter when customFieldsConfiguration is empty', () => { + expect( + constructQueryOptions({ + customFields: { second_key: [true] }, + customFieldsConfiguration: [], + }).filter + ).toBeUndefined(); + }); + + it('does not create a filter when customFields key does not match with any key of customFieldsConfiguration', () => { + expect( + constructQueryOptions({ + customFields: { random_key: [true] }, + customFieldsConfiguration, + }).filter + ).toBeUndefined(); + }); + + it('does not create a filter when no customFields mapping found', () => { + const newCustomFieldsConfiguration = [ + ...customFieldsConfiguration, + { + key: 'fourth_key', + type: 'number', + label: 'Number field', + required: true, + }, + ]; + + expect( + constructQueryOptions({ + customFields: { fourth_key: [1] }, + // @ts-expect-error: need to create a mapping check + customFieldsConfiguration: newCustomFieldsConfiguration, + }).filter + ).toBeUndefined(); + }); + }); }); describe('arraysDifference', () => { diff --git a/x-pack/plugins/cases/server/client/utils.ts b/x-pack/plugins/cases/server/client/utils.ts index 4cd8cb84e45f8..d0911758ca58f 100644 --- a/x-pack/plugins/cases/server/client/utils.ts +++ b/x-pack/plugins/cases/server/client/utils.ts @@ -19,6 +19,7 @@ import { spaceIdToNamespace } from '@kbn/spaces-plugin/server/lib/utils/namespac import type { CaseSeverity, CaseStatuses, + CustomFieldsConfiguration, ExternalReferenceAttachmentPayload, } from '../../common/types/domain'; import { @@ -31,7 +32,7 @@ import { UserCommentAttachmentPayloadRt, } from '../../common/types/domain'; import type { SavedObjectFindOptionsKueryNode } from '../common/types'; -import type { CasesFindQueryParams } from './types'; +import type { CasesSearchParams } from './types'; import { decodeWithExcessOrThrow } from '../../common/api'; import { @@ -54,6 +55,8 @@ import { } from '../common/utils'; import type { ExternalReferenceAttachmentTypeRegistry } from '../attachment_framework/external_reference_registry'; import type { AttachmentRequest, CasesFindRequestSortFields } from '../../common/types/api'; +import type { ICasesCustomField } from '../custom_fields'; +import { casesCustomFields } from '../custom_fields'; // TODO: I think we can remove most of this function since we're using a different excess export const decodeCommentRequest = ( @@ -165,9 +168,7 @@ const addSeverityFilter = (severity: CaseSeverity): KueryNode => { ); }; -const buildCategoryFilter = ( - categories: CasesFindQueryParams['category'] -): KueryNode | undefined => { +const buildCategoryFilter = (categories: CasesSearchParams['category']): KueryNode | undefined => { if (categories === undefined) { return; } @@ -302,7 +303,7 @@ export const buildRangeFilter = ({ export const buildAssigneesFilter = ({ assignees, }: { - assignees: CasesFindQueryParams['assignees']; + assignees: CasesSearchParams['assignees']; }): KueryNode | undefined => { if (assignees === undefined) { return; @@ -336,6 +337,64 @@ export const buildAssigneesFilter = ({ return nodeBuilder.or([...assigneesFilter, filterCasesWithoutAssigneesKueryNode]); }; +export const buildCustomFieldsFilter = ({ + customFields, + customFieldsConfiguration, +}: { + customFields: CasesSearchParams['customFields']; + customFieldsConfiguration?: CustomFieldsConfiguration; +}): KueryNode | undefined => { + if (!customFields || !customFieldsConfiguration?.length) { + return; + } + + const customFieldsMappings: Array> = []; + + Object.keys(customFields).forEach((item: string) => { + const customFieldConfig = customFieldsConfiguration.find((config) => config.key === item); + + if (!customFieldConfig) { + return; + } + + const mapping = casesCustomFields.get(customFieldConfig.type); + + if (!mapping) { + return; + } + + customFieldsMappings.push({ [item]: mapping }); + }); + + if (!customFieldsMappings.length) { + return; + } + + const customFieldsFilter = Object.entries(customFields).map(([key, value]) => { + const customFieldMapping = customFieldsMappings.find((mapping) => mapping[key]) ?? {}; + + if (!Object.values(value).length) { + return fromKueryExpression(`${CASE_SAVED_OBJECT}.attributes.customFields:{key: ${key}}`); + } + + return nodeBuilder.or( + Object.values(value).map((filterValue) => { + if (filterValue === null) { + return fromKueryExpression( + `${CASE_SAVED_OBJECT}.attributes.customFields:{key: ${key} and (not value:*)}` + ); + } + + return fromKueryExpression( + `${CASE_SAVED_OBJECT}.attributes.customFields:{key: ${key} and value.${customFieldMapping[key].savedObjectMappingType}: ${filterValue}}` + ); + }) + ); + }); + + return nodeBuilder.and([...customFieldsFilter]); +}; + export const constructQueryOptions = ({ tags, reporters, @@ -348,7 +407,11 @@ export const constructQueryOptions = ({ to, assignees, category, -}: CasesFindQueryParams): SavedObjectFindOptionsKueryNode => { + customFields, + customFieldsConfiguration, +}: CasesSearchParams & { + customFieldsConfiguration?: CustomFieldsConfiguration; +}): SavedObjectFindOptionsKueryNode => { const tagsFilter = buildFilter({ filters: tags, field: 'tags', operator: 'or' }); const reportersFilter = createReportersFilter(reporters); const sortByField = convertSortField(sortField); @@ -358,6 +421,7 @@ export const constructQueryOptions = ({ const rangeFilter = buildRangeFilter({ from, to }); const assigneesFilter = buildAssigneesFilter({ assignees }); const categoryFilter = buildCategoryFilter(category); + const customFieldsFilter = buildCustomFieldsFilter({ customFields, customFieldsConfiguration }); const filters = combineFilters([ statusFilter, @@ -368,6 +432,7 @@ export const constructQueryOptions = ({ ownerFilter, assigneesFilter, categoryFilter, + customFieldsFilter, ]); return { diff --git a/x-pack/plugins/cases/server/custom_fields/factory.ts b/x-pack/plugins/cases/server/custom_fields/factory.ts new file mode 100644 index 0000000000000..d9e1bc86671fe --- /dev/null +++ b/x-pack/plugins/cases/server/custom_fields/factory.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 { CustomFieldTypes } from '../../common/types/domain'; +import type { ICasesCustomField, CasesCustomFieldsMap } from './types'; +import { getCasesTextCustomField } from './text'; +import { getCasesToggleCustomField } from './toggle'; + +const mapping: Record = { + [CustomFieldTypes.TEXT]: getCasesTextCustomField(), + [CustomFieldTypes.TOGGLE]: getCasesToggleCustomField(), +}; + +export const casesCustomFields: CasesCustomFieldsMap = { + get: (type: CustomFieldTypes): ICasesCustomField | null => mapping[type] ?? null, +}; diff --git a/x-pack/plugins/reporting/server/export_types/csv_searchsource/index.ts b/x-pack/plugins/cases/server/custom_fields/index.ts similarity index 77% rename from x-pack/plugins/reporting/server/export_types/csv_searchsource/index.ts rename to x-pack/plugins/cases/server/custom_fields/index.ts index 0656f8593a514..ace73a6014106 100644 --- a/x-pack/plugins/reporting/server/export_types/csv_searchsource/index.ts +++ b/x-pack/plugins/cases/server/custom_fields/index.ts @@ -5,4 +5,5 @@ * 2.0. */ -export { CsvSearchSourceExportType } from './csv_searchsource'; +export * from './types'; +export { casesCustomFields } from './factory'; diff --git a/x-pack/plugins/cases/server/custom_fields/text.ts b/x-pack/plugins/cases/server/custom_fields/text.ts new file mode 100644 index 0000000000000..9a627dce109cc --- /dev/null +++ b/x-pack/plugins/cases/server/custom_fields/text.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 Boom from '@hapi/boom'; +import { isString } from 'lodash'; + +export const getCasesTextCustomField = () => ({ + isFilterable: false, + isSortable: false, + savedObjectMappingType: 'string', + validateFilteringValues: (values: Array) => { + values.forEach((value) => { + if (value !== null && !isString(value)) { + throw Boom.badRequest(`Unsupported filtering value for custom field of type text.`); + } + }); + }, +}); diff --git a/x-pack/plugins/cases/server/custom_fields/toggle.ts b/x-pack/plugins/cases/server/custom_fields/toggle.ts new file mode 100644 index 0000000000000..c250bf85ea168 --- /dev/null +++ b/x-pack/plugins/cases/server/custom_fields/toggle.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 Boom from '@hapi/boom'; +import { isBoolean } from 'lodash'; + +export const getCasesToggleCustomField = () => ({ + isFilterable: true, + isSortable: false, + savedObjectMappingType: 'boolean', + validateFilteringValues: (values: Array) => { + values.forEach((value) => { + if (value !== null && !isBoolean(value)) { + throw Boom.badRequest(`Unsupported filtering value for custom field of type toggle.`); + } + }); + }, +}); diff --git a/x-pack/plugins/cases/server/custom_fields/types.ts b/x-pack/plugins/cases/server/custom_fields/types.ts new file mode 100644 index 0000000000000..7a0df91682a68 --- /dev/null +++ b/x-pack/plugins/cases/server/custom_fields/types.ts @@ -0,0 +1,19 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type { CustomFieldTypes } from '../../common/types/domain'; + +export interface ICasesCustomField { + isFilterable: boolean; + isSortable: boolean; + savedObjectMappingType: string; + validateFilteringValues: (values: Array) => void; +} + +export interface CasesCustomFieldsMap { + get: (type: CustomFieldTypes) => ICasesCustomField | null; +} diff --git a/x-pack/plugins/cases/server/files/index.test.ts b/x-pack/plugins/cases/server/files/index.test.ts index 29c58c8b1d685..177392660225c 100644 --- a/x-pack/plugins/cases/server/files/index.test.ts +++ b/x-pack/plugins/cases/server/files/index.test.ts @@ -122,6 +122,11 @@ describe('server files', () => { "allowedMimeTypes": Array [ "image/png", ], + "hashes": Array [ + "md5", + "sha1", + "sha256", + ], "http": Object { "create": Object { "tags": Array [ @@ -160,6 +165,11 @@ describe('server files', () => { "allowedMimeTypes": Array [ "image/png", ], + "hashes": Array [ + "md5", + "sha1", + "sha256", + ], "http": Object { "create": Object { "tags": Array [ @@ -198,6 +208,11 @@ describe('server files', () => { "allowedMimeTypes": Array [ "image/png", ], + "hashes": Array [ + "md5", + "sha1", + "sha256", + ], "http": Object { "create": Object { "tags": Array [ @@ -238,6 +253,11 @@ describe('server files', () => { Array [ Object { "allowedMimeTypes": Array [], + "hashes": Array [ + "md5", + "sha1", + "sha256", + ], "http": Object { "create": Object { "tags": Array [ @@ -274,6 +294,11 @@ describe('server files', () => { Array [ Object { "allowedMimeTypes": Array [], + "hashes": Array [ + "md5", + "sha1", + "sha256", + ], "http": Object { "create": Object { "tags": Array [ @@ -310,6 +335,11 @@ describe('server files', () => { Array [ Object { "allowedMimeTypes": Array [], + "hashes": Array [ + "md5", + "sha1", + "sha256", + ], "http": Object { "create": Object { "tags": Array [ @@ -439,6 +469,11 @@ describe('server files', () => { "application/x-tar", "application/pdf", ], + "hashes": Array [ + "md5", + "sha1", + "sha256", + ], "http": Object { "create": Object { "tags": Array [ @@ -563,6 +598,11 @@ describe('server files', () => { "application/x-tar", "application/pdf", ], + "hashes": Array [ + "md5", + "sha1", + "sha256", + ], "http": Object { "create": Object { "tags": Array [ @@ -687,6 +727,11 @@ describe('server files', () => { "application/x-tar", "application/pdf", ], + "hashes": Array [ + "md5", + "sha1", + "sha256", + ], "http": Object { "create": Object { "tags": Array [ diff --git a/x-pack/plugins/cases/server/files/index.ts b/x-pack/plugins/cases/server/files/index.ts index af8f0c1440277..b1e7f6cf9c0f0 100644 --- a/x-pack/plugins/cases/server/files/index.ts +++ b/x-pack/plugins/cases/server/files/index.ts @@ -26,6 +26,7 @@ const buildFileKind = (config: FilesConfig, owner: Owner): FileKind => { http: fileKindHttpTags(owner), maxSizeBytes: createMaxCallback(config), allowedMimeTypes: config.allowedMimeTypes, + hashes: ['md5', 'sha1', 'sha256'], }; }; diff --git a/x-pack/plugins/cases/server/index.ts b/x-pack/plugins/cases/server/index.ts index b1cadb43f147c..911c59bc4d46a 100644 --- a/x-pack/plugins/cases/server/index.ts +++ b/x-pack/plugins/cases/server/index.ts @@ -9,7 +9,6 @@ import type { PluginConfigDescriptor, PluginInitializerContext } from '@kbn/core export { CasesClient } from './client'; import type { ConfigType } from './config'; import { ConfigSchema } from './config'; -import { CasePlugin } from './plugin'; export const config: PluginConfigDescriptor = { schema: ConfigSchema, @@ -22,7 +21,9 @@ export const config: PluginConfigDescriptor = { renameFromRoot('xpack.case.enabled', 'xpack.cases.enabled', { level: 'critical' }), ], }; -export const plugin = (initializerContext: PluginInitializerContext) => - new CasePlugin(initializerContext); +export const plugin = async (initializerContext: PluginInitializerContext) => { + const { CasePlugin } = await import('./plugin'); + return new CasePlugin(initializerContext); +}; export type { CasesSetup, CasesStart } from './types'; diff --git a/x-pack/plugins/cases/server/routes/api/cases/find_cases.ts b/x-pack/plugins/cases/server/routes/api/cases/find_cases.ts index bb14557c58ae5..1bfb5b4007c11 100644 --- a/x-pack/plugins/cases/server/routes/api/cases/find_cases.ts +++ b/x-pack/plugins/cases/server/routes/api/cases/find_cases.ts @@ -17,9 +17,10 @@ export const findCaseRoute = createCasesRoute({ try { const caseContext = await context.cases; const casesClient = await caseContext.getCasesClient(); + const options = request.query as caseApiV1.CasesFindRequest; - const res: caseApiV1.CasesFindResponse = await casesClient.cases.find({ ...options }); + const res: caseApiV1.CasesFindResponse = await casesClient.cases.search({ ...options }); return response.ok({ body: res, diff --git a/x-pack/plugins/cases/server/routes/api/get_internal_routes.ts b/x-pack/plugins/cases/server/routes/api/get_internal_routes.ts index a28d254161d07..e6c5793064545 100644 --- a/x-pack/plugins/cases/server/routes/api/get_internal_routes.ts +++ b/x-pack/plugins/cases/server/routes/api/get_internal_routes.ts @@ -18,6 +18,7 @@ import { bulkDeleteFileAttachments } from './internal/bulk_delete_file_attachmen import { getCategoriesRoute } from './cases/categories/get_categories'; import { getCaseMetricRoute } from './internal/get_case_metrics'; import { getCasesMetricRoute } from './internal/get_cases_metrics'; +import { searchCasesRoute } from './internal/search_cases'; export const getInternalRoutes = (userProfileService: UserProfileService) => [ @@ -32,4 +33,5 @@ export const getInternalRoutes = (userProfileService: UserProfileService) => getCategoriesRoute, getCaseMetricRoute, getCasesMetricRoute, + searchCasesRoute, ] as CaseRoute[]; diff --git a/x-pack/plugins/cases/server/routes/api/internal/search_cases.ts b/x-pack/plugins/cases/server/routes/api/internal/search_cases.ts new file mode 100644 index 0000000000000..193b9dab70649 --- /dev/null +++ b/x-pack/plugins/cases/server/routes/api/internal/search_cases.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 Boom from '@hapi/boom'; + +import { CASES_INTERNAL_URL } from '../../../../common/constants'; +import { createCaseError } from '../../../common/error'; +import { createCasesRoute } from '../create_cases_route'; +import type { caseApiV1 } from '../../../../common/types/api'; + +export const searchCasesRoute = createCasesRoute({ + method: 'post', + path: `${CASES_INTERNAL_URL}/_search`, + handler: async ({ context, request, response }) => { + try { + const caseContext = await context.cases; + const casesClient = await caseContext.getCasesClient(); + + const options = request.body as caseApiV1.CasesSearchRequest; + + /** + * throw error if request body does not have owner + */ + if (!Object.hasOwn(options, 'owner')) { + throw Boom.badRequest('Owner is required.'); + } + + const res: caseApiV1.CasesFindResponse = await casesClient.cases.search({ ...options }); + + return response.ok({ + body: res, + }); + } catch (error) { + throw createCaseError({ + message: `Failed to find cases in route: ${error}`, + error, + }); + } + }, +}); diff --git a/x-pack/plugins/cloud/server/index.ts b/x-pack/plugins/cloud/server/index.ts index 0328ebe89e1cf..c9d5c44390442 100644 --- a/x-pack/plugins/cloud/server/index.ts +++ b/x-pack/plugins/cloud/server/index.ts @@ -6,10 +6,10 @@ */ import { PluginInitializerContext } from '@kbn/core/server'; -import { CloudPlugin } from './plugin'; export type { CloudSetup, CloudStart } from './plugin'; export { config } from './config'; -export const plugin = (initializerContext: PluginInitializerContext) => { +export const plugin = async (initializerContext: PluginInitializerContext) => { + const { CloudPlugin } = await import('./plugin'); return new CloudPlugin(initializerContext); }; diff --git a/x-pack/plugins/cloud_defend/server/index.ts b/x-pack/plugins/cloud_defend/server/index.ts index 2cb2e1c2b55e5..c03b311bd2494 100644 --- a/x-pack/plugins/cloud_defend/server/index.ts +++ b/x-pack/plugins/cloud_defend/server/index.ts @@ -6,12 +6,12 @@ */ import { PluginInitializerContext } from '@kbn/core/server'; -import { CloudDefendPlugin } from './plugin'; // This exports static code and TypeScript types, // as well as, Kibana Platform `plugin()` initializer. -export function plugin(initializerContext: PluginInitializerContext) { +export async function plugin(initializerContext: PluginInitializerContext) { + const { CloudDefendPlugin } = await import('./plugin'); return new CloudDefendPlugin(initializerContext); } diff --git a/x-pack/plugins/cloud_integrations/cloud_chat/server/index.ts b/x-pack/plugins/cloud_integrations/cloud_chat/server/index.ts index 71f0c7c23355e..fee69b5f756fc 100755 --- a/x-pack/plugins/cloud_integrations/cloud_chat/server/index.ts +++ b/x-pack/plugins/cloud_integrations/cloud_chat/server/index.ts @@ -6,10 +6,10 @@ */ import type { PluginInitializerContext } from '@kbn/core/server'; -import { CloudChatPlugin } from './plugin'; export { config } from './config'; -export function plugin(initializerContext: PluginInitializerContext) { +export async function plugin(initializerContext: PluginInitializerContext) { + const { CloudChatPlugin } = await import('./plugin'); return new CloudChatPlugin(initializerContext); } diff --git a/x-pack/plugins/cloud_integrations/cloud_data_migration/server/index.ts b/x-pack/plugins/cloud_integrations/cloud_data_migration/server/index.ts index 5d5388e653cc8..91f0552696bae 100644 --- a/x-pack/plugins/cloud_integrations/cloud_data_migration/server/index.ts +++ b/x-pack/plugins/cloud_integrations/cloud_data_migration/server/index.ts @@ -5,8 +5,9 @@ * 2.0. */ -import { CloudDataMigrationPlugin } from './plugin'; - export { config } from './config'; -export const plugin = () => new CloudDataMigrationPlugin(); +export const plugin = async () => { + const { CloudDataMigrationPlugin } = await import('./plugin'); + return new CloudDataMigrationPlugin(); +}; diff --git a/x-pack/plugins/cloud_integrations/cloud_experiments/server/index.ts b/x-pack/plugins/cloud_integrations/cloud_experiments/server/index.ts index 6222c8108c0f5..ebf82f07ea4c9 100755 --- a/x-pack/plugins/cloud_integrations/cloud_experiments/server/index.ts +++ b/x-pack/plugins/cloud_integrations/cloud_experiments/server/index.ts @@ -6,10 +6,10 @@ */ import type { PluginInitializerContext } from '@kbn/core/server'; -import { CloudExperimentsPlugin } from './plugin'; export { config } from './config'; -export function plugin(initializerContext: PluginInitializerContext) { +export async function plugin(initializerContext: PluginInitializerContext) { + const { CloudExperimentsPlugin } = await import('./plugin'); return new CloudExperimentsPlugin(initializerContext); } diff --git a/x-pack/plugins/cloud_integrations/cloud_full_story/server/index.ts b/x-pack/plugins/cloud_integrations/cloud_full_story/server/index.ts index fe50e3d2944c3..55b049d66e264 100755 --- a/x-pack/plugins/cloud_integrations/cloud_full_story/server/index.ts +++ b/x-pack/plugins/cloud_integrations/cloud_full_story/server/index.ts @@ -6,10 +6,10 @@ */ import { PluginInitializerContext } from '@kbn/core/server'; -import { CloudFullStoryPlugin } from './plugin'; export { config } from './config'; -export function plugin(initializerContext: PluginInitializerContext) { +export async function plugin(initializerContext: PluginInitializerContext) { + const { CloudFullStoryPlugin } = await import('./plugin'); return new CloudFullStoryPlugin(initializerContext); } diff --git a/x-pack/plugins/cloud_integrations/cloud_gain_sight/server/index.ts b/x-pack/plugins/cloud_integrations/cloud_gain_sight/server/index.ts index 3e104ddd68f6c..09d79aabf8f4d 100755 --- a/x-pack/plugins/cloud_integrations/cloud_gain_sight/server/index.ts +++ b/x-pack/plugins/cloud_integrations/cloud_gain_sight/server/index.ts @@ -6,10 +6,10 @@ */ import { PluginInitializerContext } from '@kbn/core/server'; -import { CloudGainsightPlugin } from './plugin'; export { config } from './config'; -export function plugin(initializerContext: PluginInitializerContext) { +export async function plugin(initializerContext: PluginInitializerContext) { + const { CloudGainsightPlugin } = await import('./plugin'); return new CloudGainsightPlugin(initializerContext); } diff --git a/x-pack/plugins/cloud_security_posture/server/create_transforms/latest_findings_transform.ts b/x-pack/plugins/cloud_security_posture/server/create_transforms/latest_findings_transform.ts index 0b01724870e8c..21f25edf17783 100644 --- a/x-pack/plugins/cloud_security_posture/server/create_transforms/latest_findings_transform.ts +++ b/x-pack/plugins/cloud_security_posture/server/create_transforms/latest_findings_transform.ts @@ -38,6 +38,7 @@ export const latestFindingsTransform: TransformPutTransformRequest = { sort: '@timestamp', unique_key: ['resource.id', 'rule.id'], }, + settings: { unattended: true }, _meta: { package: { name: CLOUD_SECURITY_POSTURE_PACKAGE_NAME, diff --git a/x-pack/plugins/cloud_security_posture/server/create_transforms/latest_vulnerabilities_transforms.ts b/x-pack/plugins/cloud_security_posture/server/create_transforms/latest_vulnerabilities_transforms.ts index fcd3faee437a2..13f130784892c 100644 --- a/x-pack/plugins/cloud_security_posture/server/create_transforms/latest_vulnerabilities_transforms.ts +++ b/x-pack/plugins/cloud_security_posture/server/create_transforms/latest_vulnerabilities_transforms.ts @@ -40,6 +40,7 @@ export const latestVulnerabilitiesTransform: TransformPutTransformRequest = { sort: '@timestamp', unique_key: ['vulnerability.id', 'resource.id', 'package.name', 'package.version'], }, + settings: { unattended: true }, _meta: { package: { name: CLOUD_SECURITY_POSTURE_PACKAGE_NAME, diff --git a/x-pack/plugins/cloud_security_posture/server/index.ts b/x-pack/plugins/cloud_security_posture/server/index.ts index 1462eccda6cca..038c013ba746b 100755 --- a/x-pack/plugins/cloud_security_posture/server/index.ts +++ b/x-pack/plugins/cloud_security_posture/server/index.ts @@ -5,11 +5,12 @@ * 2.0. */ import type { PluginInitializerContext } from '@kbn/core/server'; -import { CspPlugin } from './plugin'; export type { CspServerPluginSetup, CspServerPluginStart } from './types'; -export const plugin = (initializerContext: PluginInitializerContext) => - new CspPlugin(initializerContext); +export const plugin = async (initializerContext: PluginInitializerContext) => { + const { CspPlugin } = await import('./plugin'); + return new CspPlugin(initializerContext); +}; export { config } from './config'; diff --git a/x-pack/plugins/cross_cluster_replication/server/index.ts b/x-pack/plugins/cross_cluster_replication/server/index.ts index a24e95bddede1..4a4e466327763 100644 --- a/x-pack/plugins/cross_cluster_replication/server/index.ts +++ b/x-pack/plugins/cross_cluster_replication/server/index.ts @@ -6,9 +6,10 @@ */ import { PluginInitializerContext } from '@kbn/core/server'; -import { CrossClusterReplicationServerPlugin } from './plugin'; export { config } from './config'; -export const plugin = (pluginInitializerContext: PluginInitializerContext) => - new CrossClusterReplicationServerPlugin(pluginInitializerContext); +export const plugin = async (pluginInitializerContext: PluginInitializerContext) => { + const { CrossClusterReplicationServerPlugin } = await import('./plugin'); + return new CrossClusterReplicationServerPlugin(pluginInitializerContext); +}; diff --git a/x-pack/plugins/custom_branding/server/index.ts b/x-pack/plugins/custom_branding/server/index.ts index d0387671278d2..3ac85738baa6e 100755 --- a/x-pack/plugins/custom_branding/server/index.ts +++ b/x-pack/plugins/custom_branding/server/index.ts @@ -7,8 +7,7 @@ import { PluginInitializerContext } from '@kbn/core/server'; -import { CustomBrandingPlugin } from './plugin'; - -export function plugin(initializerContext: PluginInitializerContext) { +export async function plugin(initializerContext: PluginInitializerContext) { + const { CustomBrandingPlugin } = await import('./plugin'); return new CustomBrandingPlugin(initializerContext); } diff --git a/x-pack/plugins/dashboard_enhanced/server/index.ts b/x-pack/plugins/dashboard_enhanced/server/index.ts index 8fa8ea33c1788..6b436893691c1 100644 --- a/x-pack/plugins/dashboard_enhanced/server/index.ts +++ b/x-pack/plugins/dashboard_enhanced/server/index.ts @@ -6,7 +6,6 @@ */ import { PluginInitializerContext } from '@kbn/core/server'; -import { DashboardEnhancedPlugin } from './plugin'; export type { SetupContract as DashboardEnhancedSetupContract, @@ -15,6 +14,7 @@ export type { StartDependencies as DashboardEnhancedStartDependencies, } from './plugin'; -export function plugin(context: PluginInitializerContext) { +export async function plugin(context: PluginInitializerContext) { + const { DashboardEnhancedPlugin } = await import('./plugin'); return new DashboardEnhancedPlugin(context); } diff --git a/x-pack/plugins/data_visualizer/server/index.ts b/x-pack/plugins/data_visualizer/server/index.ts index 08b06005539b0..1f15b498f8777 100644 --- a/x-pack/plugins/data_visualizer/server/index.ts +++ b/x-pack/plugins/data_visualizer/server/index.ts @@ -6,6 +6,8 @@ */ import { PluginInitializerContext } from '@kbn/core/server'; -import { DataVisualizerPlugin } from './plugin'; -export const plugin = (initializerContext: PluginInitializerContext) => new DataVisualizerPlugin(); +export const plugin = async (initializerContext: PluginInitializerContext) => { + const { DataVisualizerPlugin } = await import('./plugin'); + return new DataVisualizerPlugin(); +}; diff --git a/x-pack/plugins/dataset_quality/README.md b/x-pack/plugins/dataset_quality/README.md index cd5bfc30658d4..fd38679a2d778 100755 --- a/x-pack/plugins/dataset_quality/README.md +++ b/x-pack/plugins/dataset_quality/README.md @@ -1,3 +1,53 @@ # Dataset Quality In order to make ongoing maintenance of log collection easy we want to introduce the concept of dataset quality, where users can easily get an overview on the datasets they have with information such as integration, size, last activity, among others. + +## Development + +### Tests + +#### Unit tests + +Kibana primarily uses Jest for unit testing. Each plugin or package defines a `jest.config.js` that extends a preset provided by the `@kbn/test` package. The following command runs all Dataset quality unit tests: + +``` +yarn jest --config x-pack/plugins/dataset_quality/jest.config.js +``` + +You can also run a specific test by passing the filepath as an argument, e.g.: + +``` +yarn jest --config x-pack/plugins/dataset_quality/jest.config.js x-pack/plugins/dataset_quality/server/routes/data_streams/get_data_streams/get_data_streams.test.ts +``` + +#### API integration tests + +| Option | Description | +| ------------ | ----------------------------------------------- | +| --server | Only start ES and Kibana | +| --runner | Only run tests | +| --grep | Specify the specs to run | +| --grep-files | Specify the files to run | +| --inspect | Add --inspect-brk flag to the ftr for debugging | +| --times | Repeat the test n number of times | + +The API tests are located in [`x-pack/test/dataset_quality_api_integration/`](/x-pack/test/dataset_quality_api_integration/). + +#### Start server and run test (single process) + +``` +node x-pack/plugins/dataset_quality/scripts/api [--help] +``` + +The above command will start an ES instance on http://localhost:9220, a Kibana instance on http://localhost:5620 and run the api tests. +Once the tests finish, the instances will be terminated. + +#### Start server and run test (separate processes) + +```sh +# start server +node x-pack/plugins/dataset_quality/scripts/api --server + +# run tests +node x-pack/plugins/dataset_quality/scripts/api --runner --grep-files=error_group_list +``` diff --git a/x-pack/plugins/reporting/server/export_types/csv_searchsource_immediate/types.ts b/x-pack/plugins/dataset_quality/common/fetch_options.ts similarity index 58% rename from x-pack/plugins/reporting/server/export_types/csv_searchsource_immediate/types.ts rename to x-pack/plugins/dataset_quality/common/fetch_options.ts index f5c25207c78fa..3a72a72762dee 100644 --- a/x-pack/plugins/reporting/server/export_types/csv_searchsource_immediate/types.ts +++ b/x-pack/plugins/dataset_quality/common/fetch_options.ts @@ -5,8 +5,10 @@ * 2.0. */ -export type { - FakeRequest, - JobParamsDownloadCSV, - SavedObjectServiceError, -} from '../../../common/types/export_types/csv_searchsource_immediate'; +import type { HttpFetchOptions } from '@kbn/core/public'; + +export type FetchOptions = Omit & { + pathname: string; + method?: string; + body?: any; +}; diff --git a/x-pack/plugins/dataset_quality/common/index.ts b/x-pack/plugins/dataset_quality/common/index.ts index 440e8780e6bf5..2022b51685043 100644 --- a/x-pack/plugins/dataset_quality/common/index.ts +++ b/x-pack/plugins/dataset_quality/common/index.ts @@ -6,3 +6,4 @@ */ export type { DatasetQualityConfig } from './plugin_config'; +export type { FetchOptions } from './fetch_options'; diff --git a/x-pack/plugins/dataset_quality/public/services/rest/call_api.ts b/x-pack/plugins/dataset_quality/public/services/rest/call_api.ts new file mode 100644 index 0000000000000..1b39bfc905730 --- /dev/null +++ b/x-pack/plugins/dataset_quality/public/services/rest/call_api.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 { CoreSetup, CoreStart } from '@kbn/core/public'; +import { FetchOptions } from '../../../common'; + +function getFetchOptions(fetchOptions: FetchOptions) { + const { body, ...rest } = fetchOptions; + + return { + ...rest, + ...(body !== undefined ? { body: JSON.stringify(body) } : {}), + query: { + ...fetchOptions.query, + }, + }; +} + +export type CallApi = typeof callApi; + +export async function callApi( + { http }: CoreStart | CoreSetup, + fetchOptions: FetchOptions +): Promise { + const { pathname, method = 'get', ...options } = getFetchOptions(fetchOptions); + + const lowercaseMethod = method.toLowerCase() as 'get' | 'post' | 'put' | 'delete' | 'patch'; + + const res = await http[lowercaseMethod](pathname, options); + + return res; +} diff --git a/x-pack/plugins/dataset_quality/public/services/rest/create_call_dataset_quality_api.ts b/x-pack/plugins/dataset_quality/public/services/rest/create_call_dataset_quality_api.ts new file mode 100644 index 0000000000000..47d04b309817f --- /dev/null +++ b/x-pack/plugins/dataset_quality/public/services/rest/create_call_dataset_quality_api.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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { CoreSetup, CoreStart } from '@kbn/core/public'; +import type { + ClientRequestParamsOf, + ReturnOf, + RouteRepositoryClient, +} from '@kbn/server-route-repository'; +import { formatRequest } from '@kbn/server-route-repository'; +import { FetchOptions } from '../../../common'; +import type { APIEndpoint, DatasetQualityServerRouteRepository } from '../../../server/routes'; +import { CallApi, callApi } from './call_api'; + +export type DatasetQualityClientOptions = Omit< + FetchOptions, + 'query' | 'body' | 'pathname' | 'signal' +> & { + signal: AbortSignal | null; +}; + +export type DatasetQualityClient = RouteRepositoryClient< + DatasetQualityServerRouteRepository, + DatasetQualityClientOptions +>; + +export type AutoAbortedClient = RouteRepositoryClient< + DatasetQualityServerRouteRepository, + Omit +>; + +export type APIReturnType = ReturnOf< + DatasetQualityServerRouteRepository, + TEndpoint +>; + +export type APIClientRequestParamsOf = ClientRequestParamsOf< + DatasetQualityServerRouteRepository, + TEndpoint +>; + +export let callDatasetQualityApi: DatasetQualityClient = () => { + throw new Error( + 'callDatasetQualityApi has to be initialized before used. Call createCallApi first.' + ); +}; + +export function createCallDatasetQualityApi(core: CoreStart | CoreSetup) { + callDatasetQualityApi = ((endpoint, options) => { + const { params } = options as unknown as { + params?: Partial>; + }; + + const { method, pathname } = formatRequest(endpoint, params?.path); + + return callApi(core, { + ...options, + method, + pathname, + body: params?.body, + query: params?.query, + } as unknown as Parameters[1]); + }) as DatasetQualityClient; +} diff --git a/x-pack/plugins/dataset_quality/scripts/api.js b/x-pack/plugins/dataset_quality/scripts/api.js new file mode 100644 index 0000000000000..343a1d2c29944 --- /dev/null +++ b/x-pack/plugins/dataset_quality/scripts/api.js @@ -0,0 +1,100 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +/* eslint-disable no-console */ +const { times } = require('lodash'); +const yargs = require('yargs'); +const path = require('path'); +const childProcess = require('child_process'); + +const { argv } = yargs(process.argv.slice(2)) + .option('server', { + default: false, + type: 'boolean', + description: 'Only start ES and Kibana', + }) + .option('runner', { + default: false, + type: 'boolean', + description: 'Only run tests', + }) + .option('grep', { + alias: 'spec', + type: 'string', + description: 'Specify the specs to run', + }) + .option('grep-files', { + alias: 'files', + type: 'array', + string: true, + description: 'Specify the files to run', + }) + .option('times', { + type: 'number', + description: 'Repeat the test n number of times', + }) + .check((argv) => { + const { inspect, runner } = argv; + if (inspect && !runner) { + throw new Error('--inspect can only be used with --runner'); + } else { + return true; + } + }) + .help(); + +const { server, runner, grep, grepFiles } = argv; + +const license = 'basic'; + +let ftrScript = 'functional_tests'; +if (server) { + ftrScript = 'functional_tests_server'; +} else if (runner) { + ftrScript = 'functional_test_runner'; +} + +const cmd = [ + 'node', + `../../../../scripts/${ftrScript}`, + ...(grep ? [`--grep "${grep}"`] : []), + `--config ../../../test/dataset_quality_api_integration/${license}/config.ts`, +].join(' '); + +console.log(`Running: "${cmd}"`); + +function runTests() { + childProcess.execSync(cmd, { + cwd: path.join(__dirname), + stdio: 'inherit', + env: { + ...process.env, + DATASET_QUALITY_TEST_GREP_FILES: JSON.stringify(grepFiles), + }, + }); +} + +if (argv.times) { + const runCounter = { succeeded: 0, failed: 0, remaining: argv.times }; + let exitStatus = 0; + times(argv.times, () => { + try { + runTests(); + runCounter.succeeded++; + } catch (e) { + exitStatus = 1; + runCounter.failed++; + } + runCounter.remaining--; + if (argv.times > 1) { + console.log(runCounter); + } + }); + process.exit(exitStatus); +} else { + runTests(); +} diff --git a/x-pack/plugins/dataset_quality/server/index.ts b/x-pack/plugins/dataset_quality/server/index.ts index 17b028aa19431..4a5e3ce0747c9 100644 --- a/x-pack/plugins/dataset_quality/server/index.ts +++ b/x-pack/plugins/dataset_quality/server/index.ts @@ -5,6 +5,9 @@ * 2.0. */ -import { DatasetQualityServerPlugin } from './plugin'; +import { PluginInitializerContext } from '@kbn/core-plugins-server'; -export const plugin = () => new DatasetQualityServerPlugin(); +export async function plugin(initializerContext: PluginInitializerContext) { + const { DatasetQualityServerPlugin } = await import('./plugin'); + return new DatasetQualityServerPlugin(initializerContext); +} diff --git a/x-pack/plugins/dataset_quality/server/plugin.ts b/x-pack/plugins/dataset_quality/server/plugin.ts index b673fed3ad622..c34409d697988 100644 --- a/x-pack/plugins/dataset_quality/server/plugin.ts +++ b/x-pack/plugins/dataset_quality/server/plugin.ts @@ -5,10 +5,54 @@ * 2.0. */ -import { Plugin } from '@kbn/core/server'; +import { CoreSetup, Logger, Plugin, PluginInitializerContext } from '@kbn/core/server'; +import { mapValues } from 'lodash'; +import { getDatasetQualityServerRouteRepository } from './routes'; +import { registerRoutes } from './routes/register_routes'; +import { DatasetQualityRouteHandlerResources } from './routes/types'; +import { + DatasetQualityPluginSetupDependencies, + DatasetQualityPluginStart, + DatasetQualityPluginStartDependencies, +} from './types'; export class DatasetQualityServerPlugin implements Plugin { - setup() {} + private readonly logger: Logger; - start() {} + constructor(initializerContext: PluginInitializerContext) { + this.logger = initializerContext.logger.get(); + } + + setup( + core: CoreSetup, + plugins: DatasetQualityPluginSetupDependencies + ) { + this.logger.debug('dataset_quality: Setup'); + + const resourcePlugins = mapValues(plugins, (value, key) => { + return { + setup: value, + start: () => + core.getStartServices().then((services) => { + const [, pluginsStartContracts] = services; + return pluginsStartContracts[key as keyof DatasetQualityPluginStartDependencies]; + }), + }; + }) as DatasetQualityRouteHandlerResources['plugins']; + + registerRoutes({ + core, + logger: this.logger, + repository: getDatasetQualityServerRouteRepository(), + plugins: resourcePlugins, + }); + + return {}; + } + + start() { + this.logger.debug('dataset_quality: Started'); + + return {}; + } } diff --git a/x-pack/plugins/dataset_quality/server/routes/create_datasets_quality_server_route.ts b/x-pack/plugins/dataset_quality/server/routes/create_datasets_quality_server_route.ts new file mode 100644 index 0000000000000..c76d1d800de9c --- /dev/null +++ b/x-pack/plugins/dataset_quality/server/routes/create_datasets_quality_server_route.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 { createServerRouteFactory } from '@kbn/server-route-repository'; +import { DatasetQualityRouteCreateOptions, DatasetQualityRouteHandlerResources } from './types'; + +export const createDatasetQualityServerRoute = createServerRouteFactory< + DatasetQualityRouteHandlerResources, + DatasetQualityRouteCreateOptions +>(); diff --git a/x-pack/plugins/dataset_quality/server/routes/data_streams/get_data_streams/get_data_streams.test.ts b/x-pack/plugins/dataset_quality/server/routes/data_streams/get_data_streams/get_data_streams.test.ts new file mode 100644 index 0000000000000..ef1ecdbccb1d1 --- /dev/null +++ b/x-pack/plugins/dataset_quality/server/routes/data_streams/get_data_streams/get_data_streams.test.ts @@ -0,0 +1,201 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { elasticsearchServiceMock } from '@kbn/core-elasticsearch-server-mocks'; +import { dataStreamService } from '../../../services'; + +import { getDataStreams } from '.'; + +jest.mock('../../../services/data_stream', () => { + return { + dataStreamService: { + getMatchingDataStreams: jest.fn().mockImplementation(() => { + return [ + { + name: 'logs-elastic_agent-default', + timestamp_field: { name: '@timestamp' }, + indices: [ + { + index_name: '.ds-logs-elastic_agent-default-2023.05.17-000001', + index_uuid: 'EcqQR36PTNCKVnfAftq_Rw', + }, + ], + generation: 1, + _meta: { managed_by: 'fleet', managed: true, package: { name: 'elastic_agent' } }, + status: 'YELLOW', + template: 'logs-elastic_agent', + ilm_policy: 'logs', + hidden: false, + system: false, + allow_custom_routing: false, + replicated: false, + }, + { + name: 'logs-elastic_agent.filebeat-default', + timestamp_field: { name: '@timestamp' }, + indices: [ + { + index_name: '.ds-logs-elastic_agent.filebeat-default-2023.05.17-000001', + index_uuid: 'v5uEn55TRrurU3Bf4CBtzw', + }, + ], + generation: 1, + _meta: { managed_by: 'fleet', managed: true, package: { name: 'elastic_agent' } }, + status: 'YELLOW', + template: 'logs-elastic_agent.filebeat', + ilm_policy: 'logs', + hidden: false, + system: false, + allow_custom_routing: false, + replicated: false, + }, + { + name: 'logs-elastic_agent.fleet_server-default', + timestamp_field: { name: '@timestamp' }, + indices: [ + { + index_name: '.ds-logs-elastic_agent.fleet_server-default-2023.05.17-000001', + index_uuid: 'nThe6dkaQnagAlyNsAyYsA', + }, + ], + generation: 1, + _meta: { managed_by: 'fleet', managed: true, package: { name: 'elastic_agent' } }, + status: 'YELLOW', + template: 'logs-elastic_agent.fleet_server', + ilm_policy: 'logs', + hidden: false, + system: false, + allow_custom_routing: false, + replicated: false, + }, + { + name: 'logs-elastic_agent.metricbeat-default', + timestamp_field: { name: '@timestamp' }, + indices: [ + { + index_name: '.ds-logs-elastic_agent.metricbeat-default-2023.05.17-000001', + index_uuid: 'Y5vQ7V6-QSSMM-CPdqOkCg', + }, + ], + generation: 1, + _meta: { managed_by: 'fleet', managed: true, package: { name: 'elastic_agent' } }, + status: 'YELLOW', + template: 'logs-elastic_agent.metricbeat', + ilm_policy: 'logs', + hidden: false, + system: false, + allow_custom_routing: false, + replicated: false, + }, + { + name: 'logs-test.test-default', + timestamp_field: { name: '@timestamp' }, + indices: [ + { + index_name: '.ds-logs-elastic_agent.metricbeat-default-2023.05.17-000001', + index_uuid: 'Y5vQ7V6-QSSMM-CPdqOkCg', + }, + ], + }, + ]; + }), + }, + }; +}); + +describe('getDataStreams', () => { + it('Passes the correct parameters to the DataStreamService', async () => { + const esClientMock = elasticsearchServiceMock.createElasticsearchClient(); + await getDataStreams({ + esClient: esClientMock, + type: 'logs', + datasetQuery: 'nginx', + sortOrder: 'asc', + uncategorisedOnly: true, + }); + expect(dataStreamService.getMatchingDataStreams).toHaveBeenCalledWith(expect.anything(), { + type: 'logs', + dataset: '*nginx*', + }); + }); + describe('uncategorisedOnly option', () => { + it('Returns the correct number of results when true', async () => { + const esClientMock = elasticsearchServiceMock.createElasticsearchClient(); + const results = await getDataStreams({ + esClient: esClientMock, + type: 'logs', + datasetQuery: 'nginx', + sortOrder: 'asc', + uncategorisedOnly: true, + }); + expect(results.items.length).toBe(1); + }); + it('Returns the correct number of results when false', async () => { + const esClientMock = elasticsearchServiceMock.createElasticsearchClient(); + const results = await getDataStreams({ + esClient: esClientMock, + type: 'logs', + datasetQuery: 'nginx', + sortOrder: 'asc', + uncategorisedOnly: false, + }); + expect(results.items.length).toBe(5); + }); + }); + describe('Can be sorted', () => { + it('Ascending', async () => { + const esClientMock = elasticsearchServiceMock.createElasticsearchClient(); + const results = await getDataStreams({ + esClient: esClientMock, + type: 'logs', + datasetQuery: 'nginx', + sortOrder: 'asc', + uncategorisedOnly: false, + }); + expect(results.items[0].name).toBe('logs-elastic_agent-default'); + }); + it('Descending', async () => { + const esClientMock = elasticsearchServiceMock.createElasticsearchClient(); + const results = await getDataStreams({ + esClient: esClientMock, + type: 'logs', + datasetQuery: 'nginx', + sortOrder: 'desc', + uncategorisedOnly: false, + }); + expect(results.items[0].name).toBe('logs-test.test-default'); + }); + }); + it('Formats the items correctly', async () => { + const esClientMock = elasticsearchServiceMock.createElasticsearchClient(); + const results = await getDataStreams({ + esClient: esClientMock, + type: 'logs', + sortOrder: 'desc', + uncategorisedOnly: false, + }); + expect(results.items).toEqual([ + { name: 'logs-test.test-default' }, + { + name: 'logs-elastic_agent.metricbeat-default', + integration: { name: 'elastic_agent', managed_by: 'fleet' }, + }, + { + name: 'logs-elastic_agent.fleet_server-default', + integration: { name: 'elastic_agent', managed_by: 'fleet' }, + }, + { + name: 'logs-elastic_agent.filebeat-default', + integration: { name: 'elastic_agent', managed_by: 'fleet' }, + }, + { + name: 'logs-elastic_agent-default', + integration: { name: 'elastic_agent', managed_by: 'fleet' }, + }, + ]); + }); +}); diff --git a/x-pack/plugins/dataset_quality/server/routes/data_streams/get_data_streams/index.ts b/x-pack/plugins/dataset_quality/server/routes/data_streams/get_data_streams/index.ts new file mode 100644 index 0000000000000..37181d8b8a731 --- /dev/null +++ b/x-pack/plugins/dataset_quality/server/routes/data_streams/get_data_streams/index.ts @@ -0,0 +1,55 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type { ElasticsearchClient } from '@kbn/core/server'; +import { dataStreamService } from '../../../services'; +import { DataStreamTypes } from '../../../types/data_stream'; + +export async function getDataStreams(options: { + esClient: ElasticsearchClient; + type?: DataStreamTypes; + datasetQuery?: string; + sortOrder: 'asc' | 'desc'; + uncategorisedOnly: boolean; +}) { + const { esClient, type, datasetQuery, uncategorisedOnly, sortOrder } = options; + + const allDataStreams = await dataStreamService.getMatchingDataStreams(esClient, { + type: type ?? '*', + dataset: datasetQuery ? `*${datasetQuery}*` : '*', + }); + + const filteredDataStreams = uncategorisedOnly + ? allDataStreams.filter((stream) => { + return !stream._meta || !stream._meta.managed_by || stream._meta.managed_by !== 'fleet'; + }) + : allDataStreams; + + const mappedDataStreams = filteredDataStreams.map((dataStream) => ({ + name: dataStream.name, + ...(dataStream._meta + ? { + integration: { + name: dataStream._meta?.package?.name, + managed_by: dataStream._meta?.managed_by, + }, + } + : {}), + })); + + const sortedDataStreams = mappedDataStreams.sort((a, b) => { + if (sortOrder === 'desc') { + return b.name.localeCompare(a.name); + } + + return a.name.localeCompare(b.name); + }); + + return { + items: sortedDataStreams, + }; +} diff --git a/x-pack/plugins/dataset_quality/server/routes/data_streams/get_data_streams_stats/get_data_streams_stats.test.ts b/x-pack/plugins/dataset_quality/server/routes/data_streams/get_data_streams_stats/get_data_streams_stats.test.ts new file mode 100644 index 0000000000000..c078cb24d3d28 --- /dev/null +++ b/x-pack/plugins/dataset_quality/server/routes/data_streams/get_data_streams_stats/get_data_streams_stats.test.ts @@ -0,0 +1,133 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { elasticsearchServiceMock } from '@kbn/core-elasticsearch-server-mocks'; +import { dataStreamService } from '../../../services'; + +import { getDataStreamsStats } from '.'; + +jest.mock('../../../services/data_stream', () => { + return { + dataStreamService: { + getMatchingDataStreamsStats: jest.fn().mockImplementation(() => { + return [ + { + data_stream: 'logs-elastic_agent-default', + backing_indices: 1, + store_size: '1gb', + store_size_bytes: 1170805528, + maximum_timestamp: 1698916071000, + }, + { + data_stream: 'logs-elastic_agent.filebeat-default', + backing_indices: 1, + store_size: '1.3mb', + store_size_bytes: 1459100, + maximum_timestamp: 1698902209996, + }, + { + data_stream: 'logs-elastic_agent.fleet_server-default', + backing_indices: 1, + store_size: '2.9mb', + store_size_bytes: 3052148, + maximum_timestamp: 1698914110010, + }, + { + data_stream: 'logs-elastic_agent.metricbeat-default', + backing_indices: 1, + store_size: '1.6mb', + store_size_bytes: 1704807, + maximum_timestamp: 1698672046707, + }, + { + data_stream: 'logs-test.test-default', + backing_indices: 1, + store_size: '6.2mb', + store_size_bytes: 6570447, + maximum_timestamp: 1698913802000, + }, + ]; + }), + }, + }; +}); + +describe('getDataStreams', () => { + it('Passes the correct parameters to the DataStreamService', async () => { + const esClientMock = elasticsearchServiceMock.createElasticsearchClient(); + await getDataStreamsStats({ + esClient: esClientMock, + type: 'logs', + datasetQuery: 'nginx', + sortOrder: 'asc', + }); + expect(dataStreamService.getMatchingDataStreamsStats).toHaveBeenCalledWith(expect.anything(), { + type: 'logs', + dataset: '*nginx*', + }); + }); + describe('Can be sorted', () => { + it('Ascending', async () => { + const esClientMock = elasticsearchServiceMock.createElasticsearchClient(); + const results = await getDataStreamsStats({ + esClient: esClientMock, + type: 'logs', + sortOrder: 'asc', + }); + expect(results.items[0].name).toBe('logs-elastic_agent-default'); + }); + it('Descending', async () => { + const esClientMock = elasticsearchServiceMock.createElasticsearchClient(); + const results = await getDataStreamsStats({ + esClient: esClientMock, + type: 'logs', + sortOrder: 'desc', + }); + expect(results.items[0].name).toBe('logs-test.test-default'); + }); + }); + it('Formats the items correctly', async () => { + const esClientMock = elasticsearchServiceMock.createElasticsearchClient(); + const results = await getDataStreamsStats({ + esClient: esClientMock, + type: 'logs', + sortOrder: 'desc', + }); + expect(results.items).toEqual([ + { + name: 'logs-test.test-default', + size: '6.2mb', + size_bytes: 6570447, + last_activity: 1698913802000, + }, + { + name: 'logs-elastic_agent.metricbeat-default', + size: '1.6mb', + size_bytes: 1704807, + last_activity: 1698672046707, + }, + { + name: 'logs-elastic_agent.fleet_server-default', + size: '2.9mb', + size_bytes: 3052148, + last_activity: 1698914110010, + }, + { + name: 'logs-elastic_agent.filebeat-default', + size: '1.3mb', + size_bytes: 1459100, + last_activity: 1698902209996, + }, + { + name: 'logs-elastic_agent-default', + size: '1gb', + size_bytes: 1170805528, + last_activity: 1698916071000, + }, + ]); + }); +}); diff --git a/x-pack/plugins/dataset_quality/server/routes/data_streams/get_data_streams_stats/index.ts b/x-pack/plugins/dataset_quality/server/routes/data_streams/get_data_streams_stats/index.ts new file mode 100644 index 0000000000000..2f0f8057cddef --- /dev/null +++ b/x-pack/plugins/dataset_quality/server/routes/data_streams/get_data_streams_stats/index.ts @@ -0,0 +1,45 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type { ElasticsearchClient } from '@kbn/core/server'; +import { dataStreamService } from '../../../services'; +import { DataStreamTypes } from '../../../types/data_stream'; + +export async function getDataStreamsStats(options: { + esClient: ElasticsearchClient; + type?: DataStreamTypes; + datasetQuery?: string; + sortOrder: 'asc' | 'desc'; +}) { + const { esClient, type, datasetQuery, sortOrder } = options; + + const matchingDataStreamsStats = await dataStreamService.getMatchingDataStreamsStats(esClient, { + type: type ?? '*', + dataset: datasetQuery ? `*${datasetQuery}*` : '*', + }); + + const mappedDataStreams = matchingDataStreamsStats.map((dataStream) => { + return { + name: dataStream.data_stream, + size: dataStream.store_size, + size_bytes: dataStream.store_size_bytes, + last_activity: dataStream.maximum_timestamp, + }; + }); + + const sortedDataStreams = mappedDataStreams.sort((a, b) => { + if (sortOrder === 'desc') { + return b.name.localeCompare(a.name); + } + + return a.name.localeCompare(b.name); + }); + + return { + items: sortedDataStreams, + }; +} diff --git a/x-pack/plugins/dataset_quality/server/routes/data_streams/routes.ts b/x-pack/plugins/dataset_quality/server/routes/data_streams/routes.ts new file mode 100644 index 0000000000000..f973211cc7341 --- /dev/null +++ b/x-pack/plugins/dataset_quality/server/routes/data_streams/routes.ts @@ -0,0 +1,54 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import * as t from 'io-ts'; +import { keyBy, merge, values } from 'lodash'; +import { dataStreamTypesRt, sortOrderRt } from '../../types/api_types'; +import { DataStreamsStatResponse } from '../../types/data_stream'; +import { createDatasetQualityServerRoute } from '../create_datasets_quality_server_route'; +import { getDataStreams } from './get_data_streams'; +import { getDataStreamsStats } from './get_data_streams_stats'; + +const statsRoute = createDatasetQualityServerRoute({ + endpoint: 'GET /internal/dataset_quality/data_streams/stats', + params: t.type({ + query: t.intersection([ + dataStreamTypesRt, + t.partial({ + datasetQuery: t.string, + }), + sortOrderRt, + ]), + }), + options: { + tags: [], + }, + async handler(resources): Promise { + const { context, params } = resources; + const coreContext = await context.core; + + // Query datastreams as the current user as the Kibana internal user may not have all the required permissions + const esClient = coreContext.elasticsearch.client.asCurrentUser; + + const [dataStreams, dataStreamsStats] = await Promise.all([ + getDataStreams({ + esClient, + ...params.query, + uncategorisedOnly: false, + }), + getDataStreamsStats({ esClient, ...params.query }), + ]); + + return { + items: values(merge(keyBy(dataStreams.items, 'name'), keyBy(dataStreamsStats.items, 'name'))), + }; + }, +}); + +export const dataStreamsRouteRepository = { + ...statsRoute, +}; diff --git a/x-pack/plugins/dataset_quality/server/routes/index.ts b/x-pack/plugins/dataset_quality/server/routes/index.ts new file mode 100644 index 0000000000000..bb242e0db8721 --- /dev/null +++ b/x-pack/plugins/dataset_quality/server/routes/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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import type { EndpointOf, ServerRouteRepository } from '@kbn/server-route-repository'; +import { dataStreamsRouteRepository } from './data_streams/routes'; + +function getTypedDatasetQualityServerRouteRepository() { + const repository = { + ...dataStreamsRouteRepository, + }; + + return repository; +} + +export const getDatasetQualityServerRouteRepository = (): ServerRouteRepository => { + return getTypedDatasetQualityServerRouteRepository(); +}; + +export type DatasetQualityServerRouteRepository = ReturnType< + typeof getTypedDatasetQualityServerRouteRepository +>; + +export type APIEndpoint = EndpointOf; diff --git a/x-pack/plugins/dataset_quality/server/routes/register_routes.ts b/x-pack/plugins/dataset_quality/server/routes/register_routes.ts new file mode 100644 index 0000000000000..7ebecaa1346f3 --- /dev/null +++ b/x-pack/plugins/dataset_quality/server/routes/register_routes.ts @@ -0,0 +1,93 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import { errors } from '@elastic/elasticsearch'; +import Boom from '@hapi/boom'; +import { CoreSetup, Logger, RouteRegistrar } from '@kbn/core/server'; +import { + ServerRouteRepository, + decodeRequestParams, + parseEndpoint, + routeValidationObject, +} from '@kbn/server-route-repository'; +import * as t from 'io-ts'; +import { DatasetQualityRequestHandlerContext } from '../types'; +import { DatasetQualityRouteHandlerResources } from './types'; + +interface RegisterRoutes { + core: CoreSetup; + repository: ServerRouteRepository; + logger: Logger; + plugins: DatasetQualityRouteHandlerResources['plugins']; +} + +export function registerRoutes({ repository, core, logger, plugins }: RegisterRoutes) { + const routes = Object.values(repository); + + const router = core.http.createRouter(); + + routes.forEach((route) => { + const { endpoint, options, handler, params } = route; + const { pathname, method } = parseEndpoint(endpoint); + + (router[method] as RouteRegistrar)( + { + path: pathname, + validate: routeValidationObject, + options, + }, + async (context, request, response) => { + try { + const decodedParams = decodeRequestParams( + { + params: request.params, + body: request.body, + query: request.query, + }, + params ?? t.strict({}) + ); + + const data = (await handler({ + context, + request, + logger, + params: decodedParams, + plugins, + })) as any; + + if (data === undefined) { + return response.noContent(); + } + + return response.ok({ body: data }); + } catch (error) { + if (Boom.isBoom(error)) { + logger.error(error.output.payload.message); + return response.customError({ + statusCode: error.output.statusCode, + body: { message: error.output.payload.message }, + }); + } + + logger.error(error); + const opts = { + statusCode: 500, + body: { + message: error.message, + }, + }; + + if (error instanceof errors.RequestAbortedError) { + opts.statusCode = 499; + opts.body.message = 'Client closed request'; + } + + return response.customError(opts); + } + } + ); + }); +} diff --git a/x-pack/plugins/dataset_quality/server/routes/types.ts b/x-pack/plugins/dataset_quality/server/routes/types.ts new file mode 100644 index 0000000000000..8507bcde5763e --- /dev/null +++ b/x-pack/plugins/dataset_quality/server/routes/types.ts @@ -0,0 +1,33 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import { KibanaRequest, Logger } from '@kbn/core/server'; +import { DatasetQualityServerRouteRepository } from '.'; +import { + DatasetQualityPluginSetupDependencies, + DatasetQualityPluginStartDependencies, + DatasetQualityRequestHandlerContext, +} from '../types'; + +export type { DatasetQualityServerRouteRepository }; + +export interface DatasetQualityRouteHandlerResources { + context: DatasetQualityRequestHandlerContext; + logger: Logger; + request: KibanaRequest; + plugins: { + [key in keyof DatasetQualityPluginSetupDependencies]: { + setup: Required[key]; + start: () => Promise[key]>; + }; + }; +} + +export interface DatasetQualityRouteCreateOptions { + options: { + tags: string[]; + }; +} diff --git a/x-pack/plugins/dataset_quality/server/services/data_stream.ts b/x-pack/plugins/dataset_quality/server/services/data_stream.ts new file mode 100644 index 0000000000000..e0fc6e6748829 --- /dev/null +++ b/x-pack/plugins/dataset_quality/server/services/data_stream.ts @@ -0,0 +1,63 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type { + IndicesDataStream, + IndicesDataStreamsStatsDataStreamsStatsItem, +} from '@elastic/elasticsearch/lib/api/types'; +import type { ElasticsearchClient } from '@kbn/core/server'; + +class DataStreamService { + public streamPartsToIndexPattern({ type, dataset }: { dataset: string; type: string }) { + return `${type}-${dataset}`; + } + + public async getMatchingDataStreams( + esClient: ElasticsearchClient, + dataStreamParts: { + dataset: string; + type: string; + } + ): Promise { + try { + const { data_streams: dataStreamsInfo } = await esClient.indices.getDataStream({ + name: this.streamPartsToIndexPattern(dataStreamParts), + }); + + return dataStreamsInfo; + } catch (e) { + if (e.statusCode === 404) { + return []; + } + throw e; + } + } + + public async getMatchingDataStreamsStats( + esClient: ElasticsearchClient, + dataStreamParts: { + dataset: string; + type: string; + } + ): Promise { + try { + const { data_streams: dataStreamsStats } = await esClient.indices.dataStreamsStats({ + name: this.streamPartsToIndexPattern(dataStreamParts), + human: true, + }); + + return dataStreamsStats; + } catch (e) { + if (e.statusCode === 404) { + return []; + } + throw e; + } + } +} + +export const dataStreamService = new DataStreamService(); diff --git a/x-pack/plugins/reporting/server/export_types/csv_v2/index.ts b/x-pack/plugins/dataset_quality/server/services/index.ts similarity index 83% rename from x-pack/plugins/reporting/server/export_types/csv_v2/index.ts rename to x-pack/plugins/dataset_quality/server/services/index.ts index e54b2e3a5b33c..86173c476dd0e 100644 --- a/x-pack/plugins/reporting/server/export_types/csv_v2/index.ts +++ b/x-pack/plugins/dataset_quality/server/services/index.ts @@ -5,4 +5,4 @@ * 2.0. */ -export { CsvV2ExportType } from './csv_v2'; +export { dataStreamService } from './data_stream'; diff --git a/x-pack/plugins/dataset_quality/server/test_helpers/create_dataset_quality_users/authentication.ts b/x-pack/plugins/dataset_quality/server/test_helpers/create_dataset_quality_users/authentication.ts new file mode 100644 index 0000000000000..4b30ccbf00d9b --- /dev/null +++ b/x-pack/plugins/dataset_quality/server/test_helpers/create_dataset_quality_users/authentication.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. + */ + +export enum DatasetQualityUsername { + noAccessUser = 'no_access_user', + viewerUser = 'viewer', + editorUser = 'editor', + datasetQualityLogsUser = 'dataset_quality_logs_user', +} + +export enum DatasetQualityCustomRolename { + datasetQualityLogsUser = 'dataset_quality_logs_user', +} + +export const customRoles = { + [DatasetQualityCustomRolename.datasetQualityLogsUser]: { + elasticsearch: { + indices: [ + { + names: ['logs-*-*'], + privileges: ['monitor'], + }, + ], + }, + }, +}; + +export const users: Record< + DatasetQualityUsername, + { + builtInRoleNames?: string[]; + customRoleNames?: DatasetQualityCustomRolename[]; + } +> = { + [DatasetQualityUsername.noAccessUser]: {}, + [DatasetQualityUsername.viewerUser]: { + builtInRoleNames: ['viewer'], + }, + [DatasetQualityUsername.editorUser]: { + builtInRoleNames: ['editor'], + }, + [DatasetQualityUsername.datasetQualityLogsUser]: { + builtInRoleNames: ['editor'], + customRoleNames: [DatasetQualityCustomRolename.datasetQualityLogsUser], + }, +}; + +export const DATASET_QUALITY_TEST_PASSWORD = 'changeme'; diff --git a/x-pack/plugins/dataset_quality/server/test_helpers/create_dataset_quality_users/helpers/call_kibana.ts b/x-pack/plugins/dataset_quality/server/test_helpers/create_dataset_quality_users/helpers/call_kibana.ts new file mode 100644 index 0000000000000..879b02f8a93c5 --- /dev/null +++ b/x-pack/plugins/dataset_quality/server/test_helpers/create_dataset_quality_users/helpers/call_kibana.ts @@ -0,0 +1,56 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import axios, { AxiosRequestConfig, AxiosError } from 'axios'; +import { once } from 'lodash'; +import { Elasticsearch, Kibana } from '..'; + +export async function callKibana({ + elasticsearch, + kibana, + options, +}: { + elasticsearch: Omit; + kibana: Kibana; + options: AxiosRequestConfig; +}): Promise { + const baseUrl = await getBaseUrl(kibana.hostname); + const { username, password } = elasticsearch; + + const { data } = await axios.request({ + ...options, + baseURL: baseUrl, + auth: { username, password }, + headers: { 'kbn-xsrf': 'true', ...options.headers }, + }); + return data; +} + +const getBaseUrl = once(async (kibanaHostname: string) => { + try { + await axios.request({ url: kibanaHostname, maxRedirects: 0 }); + } catch (e) { + if (isAxiosError(e)) { + const location = e.response?.headers?.location ?? ''; + const hasBasePath = RegExp(/^\/\w{3}$/).test(location); + const basePath = hasBasePath ? location : ''; + return `${kibanaHostname}${basePath}`; + } + + throw e; + } + return kibanaHostname; +}); + +export function isAxiosError(e: AxiosError | Error): e is AxiosError { + return 'isAxiosError' in e; +} + +export class AbortError extends Error { + constructor(message: string) { + super(message); + } +} diff --git a/x-pack/plugins/dataset_quality/server/test_helpers/create_dataset_quality_users/helpers/create_custom_role.ts b/x-pack/plugins/dataset_quality/server/test_helpers/create_dataset_quality_users/helpers/create_custom_role.ts new file mode 100644 index 0000000000000..141f5333c28b7 --- /dev/null +++ b/x-pack/plugins/dataset_quality/server/test_helpers/create_dataset_quality_users/helpers/create_custom_role.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 { Elasticsearch, Kibana } from '..'; +import { customRoles, DatasetQualityCustomRolename } from '../authentication'; +import { callKibana } from './call_kibana'; + +export async function createCustomRole({ + elasticsearch, + kibana, + roleName, +}: { + elasticsearch: Elasticsearch; + kibana: Kibana; + roleName: DatasetQualityCustomRolename; +}) { + const role = customRoles[roleName]; + + await callKibana({ + elasticsearch, + kibana, + options: { + method: 'PUT', + url: `/api/security/role/${roleName}`, + data: role, + }, + }); +} diff --git a/x-pack/plugins/dataset_quality/server/test_helpers/create_dataset_quality_users/helpers/create_or_update_user.ts b/x-pack/plugins/dataset_quality/server/test_helpers/create_dataset_quality_users/helpers/create_or_update_user.ts new file mode 100644 index 0000000000000..57e9e6a64c0df --- /dev/null +++ b/x-pack/plugins/dataset_quality/server/test_helpers/create_dataset_quality_users/helpers/create_or_update_user.ts @@ -0,0 +1,133 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +/* eslint-disable no-console */ + +import { difference, union } from 'lodash'; +import { Elasticsearch, Kibana } from '..'; +import { callKibana, isAxiosError } from './call_kibana'; + +interface User { + username: string; + roles: string[]; + full_name?: string; + email?: string; + enabled?: boolean; +} + +export async function createOrUpdateUser({ + elasticsearch, + kibana, + user, +}: { + elasticsearch: Elasticsearch; + kibana: Kibana; + user: User; +}) { + const existingUser = await getUser({ + elasticsearch, + kibana, + username: user.username, + }); + if (!existingUser) { + return createUser({ elasticsearch, kibana, newUser: user }); + } + + return updateUser({ + elasticsearch, + kibana, + existingUser, + newUser: user, + }); +} + +async function createUser({ + elasticsearch, + kibana, + newUser, +}: { + elasticsearch: Elasticsearch; + kibana: Kibana; + newUser: User; +}) { + const user = await callKibana({ + elasticsearch, + kibana, + options: { + method: 'POST', + url: `/internal/security/users/${newUser.username}`, + data: { + ...newUser, + enabled: true, + password: elasticsearch.password, + }, + }, + }); + + console.log(`User "${newUser.username}" was created`); + return user; +} + +async function updateUser({ + elasticsearch, + kibana, + existingUser, + newUser, +}: { + elasticsearch: Elasticsearch; + kibana: Kibana; + existingUser: User; + newUser: User; +}) { + const { username } = newUser; + const allRoles = union(existingUser.roles, newUser.roles); + const hasAllRoles = difference(allRoles, existingUser.roles).length === 0; + if (hasAllRoles) { + console.log(`Skipping: User "${username}" already has necessary roles: "${newUser.roles}"`); + return; + } + + // assign role to user + await callKibana({ + elasticsearch, + kibana, + options: { + method: 'POST', + url: `/internal/security/users/${username}`, + data: { ...existingUser, roles: allRoles }, + }, + }); + + console.log(`User "${username}" was updated`); +} + +async function getUser({ + elasticsearch, + kibana, + username, +}: { + elasticsearch: Elasticsearch; + kibana: Kibana; + username: string; +}) { + try { + return await callKibana({ + elasticsearch, + kibana, + options: { + url: `/internal/security/users/${username}`, + }, + }); + } catch (e) { + // return empty if user doesn't exist + if (isAxiosError(e) && e.response?.status === 404) { + return null; + } + + throw e; + } +} diff --git a/x-pack/plugins/dataset_quality/server/test_helpers/create_dataset_quality_users/index.ts b/x-pack/plugins/dataset_quality/server/test_helpers/create_dataset_quality_users/index.ts new file mode 100644 index 0000000000000..9cfb2f1dc66d0 --- /dev/null +++ b/x-pack/plugins/dataset_quality/server/test_helpers/create_dataset_quality_users/index.ts @@ -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 { asyncForEach } from '@kbn/std'; +import { AbortError, callKibana } from './helpers/call_kibana'; +import { createOrUpdateUser } from './helpers/create_or_update_user'; +import { DatasetQualityUsername, users } from './authentication'; +import { createCustomRole } from './helpers/create_custom_role'; + +export interface Elasticsearch { + node: string; + username: string; + password: string; +} + +export interface Kibana { + hostname: string; +} + +export async function createDatasetQualityUsers({ + kibana, + elasticsearch, +}: { + kibana: Kibana; + elasticsearch: Elasticsearch; +}) { + const isCredentialsValid = await getIsCredentialsValid({ + elasticsearch, + kibana, + }); + + if (!isCredentialsValid) { + throw new AbortError('Invalid username/password'); + } + + const isSecurityEnabled = await getIsSecurityEnabled({ + elasticsearch, + kibana, + }); + + if (!isSecurityEnabled) { + throw new AbortError('Security must be enabled!'); + } + + const datasetQualityUsers = Object.values(DatasetQualityUsername); + await asyncForEach(datasetQualityUsers, async (username) => { + const user = users[username]; + const { builtInRoleNames = [], customRoleNames = [] } = user; + + // create custom roles + await Promise.all( + customRoleNames.map(async (roleName) => createCustomRole({ elasticsearch, kibana, roleName })) + ); + + // create user + const roles = builtInRoleNames.concat(customRoleNames); + await createOrUpdateUser({ + elasticsearch, + kibana, + user: { username, roles }, + }); + }); + + return datasetQualityUsers; +} + +async function getIsSecurityEnabled({ + elasticsearch, + kibana, +}: { + elasticsearch: Elasticsearch; + kibana: Kibana; +}) { + try { + await callKibana({ + elasticsearch, + kibana, + options: { + url: `/internal/security/me`, + }, + }); + return true; + } catch (err) { + return false; + } +} + +async function getIsCredentialsValid({ + elasticsearch, + kibana, +}: { + elasticsearch: Elasticsearch; + kibana: Kibana; +}) { + try { + await callKibana({ + elasticsearch, + kibana, + options: { + validateStatus: (status) => status >= 200 && status < 400, + url: `/`, + }, + }); + return true; + } catch (err) { + return false; + } +} diff --git a/x-pack/plugins/dataset_quality/server/types.ts b/x-pack/plugins/dataset_quality/server/types.ts new file mode 100644 index 0000000000000..f9a184cfb768c --- /dev/null +++ b/x-pack/plugins/dataset_quality/server/types.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 { CustomRequestHandlerContext } from '@kbn/core/server'; + +// eslint-disable-next-line @typescript-eslint/no-empty-interface +export interface DatasetQualityPluginSetupDependencies {} + +// eslint-disable-next-line @typescript-eslint/no-empty-interface +export interface DatasetQualityPluginStartDependencies {} + +// eslint-disable-next-line @typescript-eslint/no-empty-interface +export interface DatasetQualityPluginSetup {} +// eslint-disable-next-line @typescript-eslint/no-empty-interface +export interface DatasetQualityPluginStart {} + +export type DatasetQualityRequestHandlerContext = CustomRequestHandlerContext<{}>; diff --git a/x-pack/plugins/dataset_quality/server/types/api_types.ts b/x-pack/plugins/dataset_quality/server/types/api_types.ts new file mode 100644 index 0000000000000..077cb94aa3493 --- /dev/null +++ b/x-pack/plugins/dataset_quality/server/types/api_types.ts @@ -0,0 +1,22 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 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 dataStreamTypesRt = t.partial({ + type: t.union([ + t.literal('logs'), + t.literal('metrics'), + t.literal('traces'), + t.literal('synthetics'), + t.literal('profiling'), + ]), +}); + +export const sortOrderRt = t.type({ + sortOrder: t.union([t.literal('asc'), t.literal('desc')]), +}); diff --git a/x-pack/plugins/dataset_quality/server/types/data_stream.ts b/x-pack/plugins/dataset_quality/server/types/data_stream.ts new file mode 100644 index 0000000000000..582746755ac51 --- /dev/null +++ b/x-pack/plugins/dataset_quality/server/types/data_stream.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 { ByteSize } from '@elastic/elasticsearch/lib/api/types'; + +export interface DataStreamsStatResponse { + items: DataStreamStat[]; +} + +export interface DataStreamStat { + name: string; + size?: ByteSize; + size_bytes?: number; + last_activity?: number; + integration?: { + name?: string; + managed_by?: string; + }; +} + +export type DataStreamTypes = 'logs' | 'metrics' | 'traces' | 'synthetics' | 'profiling'; diff --git a/x-pack/plugins/dataset_quality/tsconfig.json b/x-pack/plugins/dataset_quality/tsconfig.json index efe7ece5983ac..8e3ebcdb7e741 100644 --- a/x-pack/plugins/dataset_quality/tsconfig.json +++ b/x-pack/plugins/dataset_quality/tsconfig.json @@ -4,14 +4,19 @@ "outDir": "target/types" }, "include": [ - "../../../typings/**/*", "common/**/*", "public/**/*", - "server/**/*.ts", - "../../typings/**/*" + "server/**/*", + "../../../typings/**/*", ], "kbn_references": [ "@kbn/core", + "@kbn/server-route-repository", + "@kbn/core-plugins-server", + "@kbn/core-elasticsearch-server-mocks", + "@kbn/std", ], - "exclude": ["target/**/*"] + "exclude": [ + "target/**/*", + ] } diff --git a/x-pack/plugins/discover_enhanced/server/index.ts b/x-pack/plugins/discover_enhanced/server/index.ts index 95ce6a4b8d3ba..853d529d28c8e 100644 --- a/x-pack/plugins/discover_enhanced/server/index.ts +++ b/x-pack/plugins/discover_enhanced/server/index.ts @@ -6,8 +6,10 @@ */ import { PluginInitializerContext } from '@kbn/core/server'; -import { DiscoverEnhancedPlugin } from './plugin'; export { config } from './config'; -export const plugin = (context: PluginInitializerContext) => new DiscoverEnhancedPlugin(context); +export const plugin = async (context: PluginInitializerContext) => { + const { DiscoverEnhancedPlugin } = await import('./plugin'); + return new DiscoverEnhancedPlugin(context); +}; diff --git a/x-pack/plugins/ecs_data_quality_dashboard/server/index.ts b/x-pack/plugins/ecs_data_quality_dashboard/server/index.ts index e7b580e50a762..bd83becac07b3 100755 --- a/x-pack/plugins/ecs_data_quality_dashboard/server/index.ts +++ b/x-pack/plugins/ecs_data_quality_dashboard/server/index.ts @@ -6,12 +6,12 @@ */ import { PluginInitializerContext } from '@kbn/core/server'; -import { EcsDataQualityDashboardPlugin } from './plugin'; // This exports static code and TypeScript types, // as well as, Kibana Platform `plugin()` initializer. -export function plugin(initializerContext: PluginInitializerContext) { +export async function plugin(initializerContext: PluginInitializerContext) { + const { EcsDataQualityDashboardPlugin } = await import('./plugin'); return new EcsDataQualityDashboardPlugin(initializerContext); } diff --git a/x-pack/plugins/elastic_assistant/server/index.ts b/x-pack/plugins/elastic_assistant/server/index.ts index a375e036d8238..0cccc1ba27a7a 100755 --- a/x-pack/plugins/elastic_assistant/server/index.ts +++ b/x-pack/plugins/elastic_assistant/server/index.ts @@ -6,9 +6,9 @@ */ import { PluginInitializerContext } from '@kbn/core/server'; -import { ElasticAssistantPlugin } from './plugin'; -export function plugin(initializerContext: PluginInitializerContext) { +export async function plugin(initializerContext: PluginInitializerContext) { + const { ElasticAssistantPlugin } = await import('./plugin'); return new ElasticAssistantPlugin(initializerContext); } diff --git a/x-pack/plugins/encrypted_saved_objects/server/index.ts b/x-pack/plugins/encrypted_saved_objects/server/index.ts index 4a75e0f6855b8..8b3982c292caa 100644 --- a/x-pack/plugins/encrypted_saved_objects/server/index.ts +++ b/x-pack/plugins/encrypted_saved_objects/server/index.ts @@ -8,7 +8,6 @@ import type { PluginConfigDescriptor, PluginInitializerContext } from '@kbn/core/server'; import { ConfigSchema } from './config'; -import { EncryptedSavedObjectsPlugin } from './plugin'; export type { EncryptedSavedObjectTypeRegistration, AttributeToEncrypt } from './crypto'; export { EncryptionError, EncryptionErrorOperation } from './crypto'; @@ -27,5 +26,7 @@ export type { export const config: PluginConfigDescriptor = { schema: ConfigSchema, }; -export const plugin = (initializerContext: PluginInitializerContext) => - new EncryptedSavedObjectsPlugin(initializerContext); +export const plugin = async (initializerContext: PluginInitializerContext) => { + const { EncryptedSavedObjectsPlugin } = await import('./plugin'); + return new EncryptedSavedObjectsPlugin(initializerContext); +}; diff --git a/x-pack/plugins/enterprise_search/common/constants.ts b/x-pack/plugins/enterprise_search/common/constants.ts index 8f0b7a80282e2..5d7ae07a246d3 100644 --- a/x-pack/plugins/enterprise_search/common/constants.ts +++ b/x-pack/plugins/enterprise_search/common/constants.ts @@ -197,7 +197,7 @@ export const DEFAULT_PIPELINE_VALUES: IngestPipelineParams = { extract_binary_content: true, name: DEFAULT_PIPELINE_NAME, reduce_whitespace: true, - run_ml_inference: false, + run_ml_inference: true, }; export interface DefaultConnectorsPipelineMeta { diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ingest_pipelines/ingest_pipelines_card.test.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ingest_pipelines/ingest_pipelines_card.test.tsx index 3b3e80d4d9758..0028d2aff6d3d 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ingest_pipelines/ingest_pipelines_card.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ingest_pipelines/ingest_pipelines_card.test.tsx @@ -33,7 +33,7 @@ const DEFAULT_VALUES = { extract_binary_content: true, name: DEFAULT_PIPELINE_NAME, reduce_whitespace: true, - run_ml_inference: false, + run_ml_inference: true, }, showModal: false, }; diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/pipelines_logic.test.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/pipelines_logic.test.ts index 69e01d45750fe..df02a53fe0ab0 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/pipelines_logic.test.ts +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/pipelines_logic.test.ts @@ -23,7 +23,7 @@ const DEFAULT_PIPELINE_VALUES = { extract_binary_content: true, name: 'ent-search-generic-ingestion', reduce_whitespace: true, - run_ml_inference: false, + run_ml_inference: true, }; const DEFAULT_VALUES = { @@ -104,6 +104,7 @@ describe('PipelinesLogic', () => { }); expect(PipelinesLogic.values).toEqual({ ...DEFAULT_VALUES, + canUseMlInferencePipeline: true, hasIndexIngestionPipeline: true, pipelineName: 'new_pipeline_name', pipelineState: { ...DEFAULT_PIPELINE_VALUES, name: 'new_pipeline_name' }, diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_indices/search_indices.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_indices/search_indices.tsx index 7085784d660f2..8e778228857e1 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_indices/search_indices.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_indices/search_indices.tsx @@ -319,7 +319,6 @@ export const SearchIndices: React.FC = () => { )} - ) ); }; diff --git a/x-pack/plugins/enterprise_search/server/index.ts b/x-pack/plugins/enterprise_search/server/index.ts index 3b9372f339acf..53d8cbca7f540 100644 --- a/x-pack/plugins/enterprise_search/server/index.ts +++ b/x-pack/plugins/enterprise_search/server/index.ts @@ -8,9 +8,8 @@ import { schema, TypeOf } from '@kbn/config-schema'; import { PluginInitializerContext, PluginConfigDescriptor } from '@kbn/core/server'; -import { EnterpriseSearchPlugin } from './plugin'; - -export const plugin = (initializerContext: PluginInitializerContext) => { +export const plugin = async (initializerContext: PluginInitializerContext) => { + const { EnterpriseSearchPlugin } = await import('./plugin'); return new EnterpriseSearchPlugin(initializerContext); }; diff --git a/x-pack/plugins/enterprise_search/server/lib/connectors/add_connector.test.ts b/x-pack/plugins/enterprise_search/server/lib/connectors/add_connector.test.ts index cd15faf6b90c1..9bb2a18d6a4bb 100644 --- a/x-pack/plugins/enterprise_search/server/lib/connectors/add_connector.test.ts +++ b/x-pack/plugins/enterprise_search/server/lib/connectors/add_connector.test.ts @@ -52,7 +52,7 @@ describe('addConnector lib function', () => { default_extract_binary_content: true, default_name: 'ent-search-generic-ingestion', default_reduce_whitespace: true, - default_run_ml_inference: false, + default_run_ml_inference: true, }, version: '1', }, @@ -87,7 +87,7 @@ describe('addConnector lib function', () => { extract_binary_content: true, name: 'ent-search-generic-ingestion', reduce_whitespace: true, - run_ml_inference: false, + run_ml_inference: true, }, }); expect(mockClient.asCurrentUser.indices.create).toHaveBeenCalledWith({ @@ -205,7 +205,7 @@ describe('addConnector lib function', () => { extract_binary_content: true, name: 'ent-search-generic-ingestion', reduce_whitespace: true, - run_ml_inference: false, + run_ml_inference: true, }, }); expect(mockClient.asCurrentUser.indices.create).toHaveBeenCalledWith({ diff --git a/x-pack/plugins/enterprise_search/server/lib/pipelines/get_index_pipeline.test.ts b/x-pack/plugins/enterprise_search/server/lib/pipelines/get_index_pipeline.test.ts index 58476ed18b741..07260423b4590 100644 --- a/x-pack/plugins/enterprise_search/server/lib/pipelines/get_index_pipeline.test.ts +++ b/x-pack/plugins/enterprise_search/server/lib/pipelines/get_index_pipeline.test.ts @@ -87,7 +87,7 @@ describe('getIndexPipelineParameters', () => { extract_binary_content: true, name: 'my-index', reduce_whitespace: true, - run_ml_inference: false, + run_ml_inference: true, }); }); it('returns default connector index pipeline if found in mapping', async () => { diff --git a/x-pack/plugins/event_log/server/index.ts b/x-pack/plugins/event_log/server/index.ts index cd386483fef8f..e070f0cf0c940 100644 --- a/x-pack/plugins/event_log/server/index.ts +++ b/x-pack/plugins/event_log/server/index.ts @@ -7,7 +7,6 @@ import { PluginInitializerContext, PluginConfigDescriptor } from '@kbn/core/server'; import { ConfigSchema, IEventLogConfig } from './types'; -import { Plugin } from './plugin'; export { millisToNanos, nanosToMillis } from '../common'; @@ -30,4 +29,7 @@ export { createReadySignal } from './lib/ready_signal'; export const config: PluginConfigDescriptor = { schema: ConfigSchema, }; -export const plugin = (context: PluginInitializerContext) => new Plugin(context); +export const plugin = async (context: PluginInitializerContext) => { + const { Plugin } = await import('./plugin'); + return new Plugin(context); +}; diff --git a/x-pack/plugins/features/server/index.ts b/x-pack/plugins/features/server/index.ts index 5882d0a4e339a..b40094dee92d4 100644 --- a/x-pack/plugins/features/server/index.ts +++ b/x-pack/plugins/features/server/index.ts @@ -6,7 +6,6 @@ */ import { PluginInitializerContext } from '@kbn/core/server'; -import { FeaturesPlugin } from './plugin'; // These exports are part of public Features plugin contract, any change in signature of exported // functions or removal of exports should be considered as a breaking change. Ideally we should @@ -23,5 +22,7 @@ export type { export { KibanaFeature, ElasticsearchFeature } from '../common'; export type { PluginSetupContract, PluginStartContract } from './plugin'; -export const plugin = (initializerContext: PluginInitializerContext) => - new FeaturesPlugin(initializerContext); +export const plugin = async (initializerContext: PluginInitializerContext) => { + const { FeaturesPlugin } = await import('./plugin'); + return new FeaturesPlugin(initializerContext); +}; diff --git a/x-pack/plugins/file_upload/server/index.ts b/x-pack/plugins/file_upload/server/index.ts index c818e74c0ddc5..8078c19cc4f6f 100644 --- a/x-pack/plugins/file_upload/server/index.ts +++ b/x-pack/plugins/file_upload/server/index.ts @@ -6,7 +6,8 @@ */ import { PluginInitializerContext } from '@kbn/core/server'; -import { FileUploadPlugin } from './plugin'; -export const plugin = (initializerContext: PluginInitializerContext) => - new FileUploadPlugin(initializerContext); +export const plugin = async (initializerContext: PluginInitializerContext) => { + const { FileUploadPlugin } = await import('./plugin'); + return new FileUploadPlugin(initializerContext); +}; diff --git a/x-pack/plugins/fleet/.storybook/context/ui_settings.ts b/x-pack/plugins/fleet/.storybook/context/ui_settings.ts index b5757c84875f7..6dec0c3764d59 100644 --- a/x-pack/plugins/fleet/.storybook/context/ui_settings.ts +++ b/x-pack/plugins/fleet/.storybook/context/ui_settings.ts @@ -26,6 +26,9 @@ const uiSettings: IUiSettingsClient = { set: async () => true, getUpdate$: () => of({ key: 'setting', newValue: get('setting'), oldValue: get('setting') }), getUpdateErrors$: () => of(new Error()), + validateValue: async () => { + return { successfulValidation: true, valid: true }; + }, }; export const getUiSettings = () => uiSettings; diff --git a/x-pack/plugins/fleet/common/services/is_agent_upgradeable.test.ts b/x-pack/plugins/fleet/common/services/is_agent_upgradeable.test.ts index ad8138abbce7f..7ab016239702d 100644 --- a/x-pack/plugins/fleet/common/services/is_agent_upgradeable.test.ts +++ b/x-pack/plugins/fleet/common/services/is_agent_upgradeable.test.ts @@ -5,23 +5,29 @@ * 2.0. */ -import type { Agent } from '../types/models/agent'; +import type { Agent, AgentUpgradeDetails } from '../types/models/agent'; -import { getRecentUpgradeInfoForAgent, isAgentUpgradeable } from './is_agent_upgradeable'; +import { + getRecentUpgradeInfoForAgent, + isAgentUpgradeable, + isAgentUpgrading, +} from './is_agent_upgradeable'; const getAgent = ({ version, upgradeable = false, unenrolling = false, unenrolled = false, - updating = false, + upgrading = false, + upgradeDetails, minutesSinceUpgrade, }: { version: string; upgradeable?: boolean; unenrolling?: boolean; unenrolled?: boolean; - updating?: boolean; + upgrading?: boolean; + upgradeDetails?: AgentUpgradeDetails; minutesSinceUpgrade?: number; }): Agent => { const agent: Agent = { @@ -98,9 +104,12 @@ const getAgent = ({ if (unenrolled) { agent.unenrolled_at = '2020-10-01T14:43:27.255Z'; } - if (updating) { + if (upgrading) { agent.upgrade_started_at = new Date(Date.now()).toISOString(); } + if (upgradeDetails) { + agent.upgrade_details = upgradeDetails; + } if (minutesSinceUpgrade) { agent.upgraded_at = new Date(Date.now() - minutesSinceUpgrade * 6e4).toISOString(); } @@ -171,11 +180,49 @@ describe('Fleet - isAgentUpgradeable', () => { isAgentUpgradeable(getAgent({ version: '7.9.0', upgradeable: true }), '8.0.0', '7.9.0') ).toBe(false); }); - it('returns false if agent reports upgradeable, but is already updating', () => { + it('returns false if agent with no upgrade details reports upgradeable, but is already upgrading', () => { + expect( + isAgentUpgradeable( + getAgent({ version: '7.9.0', upgradeable: true, upgrading: true }), + '8.0.0' + ) + ).toBe(false); + }); + it('returns false if agent reports upgradeable, but has an upgrade status other than failed', () => { expect( - isAgentUpgradeable(getAgent({ version: '7.9.0', upgradeable: true, updating: true }), '8.0.0') + isAgentUpgradeable( + getAgent({ + version: '7.9.0', + upgradeable: true, + upgradeDetails: { + target_version: '8.0.0', + action_id: 'XXX', + state: 'UPG_REQUESTED', + }, + }), + '8.0.0' + ) ).toBe(false); }); + it('returns true if agent reports upgradeable and has a failed upgrade status', () => { + expect( + isAgentUpgradeable( + getAgent({ + version: '7.9.0', + upgradeable: true, + upgradeDetails: { + target_version: '8.0.0', + action_id: 'XXX', + state: 'UPG_FAILED', + metadata: { + error_msg: 'Upgrade timed out', + }, + }, + }), + '8.0.0' + ) + ).toBe(true); + }); it('returns false if the agent reports upgradeable but was upgraded less than 10 minutes ago', () => { expect( isAgentUpgradeable( @@ -215,3 +262,49 @@ describe('hasAgentBeenUpgradedRecently', () => { ).toBe(false); }); }); + +describe('isAgentUpgrading', () => { + it('returns true if the agent has an upgrade status other than failed', () => { + expect( + isAgentUpgrading( + getAgent({ + version: '7.9.0', + upgradeDetails: { + target_version: '8.0.0', + action_id: 'XXX', + state: 'UPG_REQUESTED', + }, + }) + ) + ).toBe(true); + }); + + it('returns false if the agent has a failed upgrade status', () => { + expect( + isAgentUpgrading( + getAgent({ + version: '7.9.0', + upgradeDetails: { + target_version: '8.0.0', + action_id: 'XXX', + state: 'UPG_FAILED', + metadata: { + error_msg: 'Upgrade timed out', + }, + }, + }) + ) + ).toBe(false); + }); + + it('returns true if the agent is upgrading but has no upgrade details', () => { + expect( + isAgentUpgrading( + getAgent({ + version: '7.9.0', + upgrading: true, + }) + ) + ).toBe(true); + }); +}); diff --git a/x-pack/plugins/fleet/common/services/is_agent_upgradeable.ts b/x-pack/plugins/fleet/common/services/is_agent_upgradeable.ts index c7bd21c45af4a..ac21e24520c76 100644 --- a/x-pack/plugins/fleet/common/services/is_agent_upgradeable.ts +++ b/x-pack/plugins/fleet/common/services/is_agent_upgradeable.ts @@ -30,11 +30,9 @@ export function isAgentUpgradeable( if (!agent.local_metadata.elastic.agent.upgradeable) { return false; } - // check that the agent is not already in the process of updating - if (agent.upgrade_started_at && !agent.upgraded_at) { + if (isAgentUpgrading(agent)) { return false; } - // check that the agent has not been upgraded more recently than the monitoring period if (getRecentUpgradeInfoForAgent(agent).hasBeenUpgradedRecently) { return false; } @@ -80,3 +78,10 @@ export function getRecentUpgradeInfoForAgent(agent: Agent): { return { hasBeenUpgradedRecently, timeToWaitMs }; } + +export function isAgentUpgrading(agent: Agent) { + if (agent.upgrade_details) { + return agent.upgrade_details.state !== 'UPG_FAILED'; + } + return agent.upgrade_started_at && !agent.upgraded_at; +} diff --git a/x-pack/plugins/fleet/common/types/models/agent.ts b/x-pack/plugins/fleet/common/types/models/agent.ts index 934ca7ecd2641..120f0bc883e1d 100644 --- a/x-pack/plugins/fleet/common/types/models/agent.ts +++ b/x-pack/plugins/fleet/common/types/models/agent.ts @@ -443,7 +443,7 @@ export interface AgentUpgradeDetails { target_version: string; action_id: string; state: AgentUpgradeStateType; - metadata: { + metadata?: { scheduled_at?: string; download_percent?: number; failed_state?: AgentUpgradeStateType; diff --git a/x-pack/plugins/fleet/common/types/models/package_spec.ts b/x-pack/plugins/fleet/common/types/models/package_spec.ts index 60bc051af04fc..9a42745cd89bb 100644 --- a/x-pack/plugins/fleet/common/types/models/package_spec.ts +++ b/x-pack/plugins/fleet/common/types/models/package_spec.ts @@ -26,7 +26,7 @@ export interface PackageSpecManifest { screenshots?: PackageSpecScreenshot[]; policy_templates?: RegistryPolicyTemplate[]; vars?: RegistryVarsEntry[]; - owner: { github: string }; + owner: { github: string; type?: 'elastic' | 'partner' | 'community' }; elasticsearch?: Pick< RegistryElasticsearch, 'index_template.settings' | 'index_template.mappings' | 'index_template.data_stream' diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/components/steps/components/package_policy_input_var_field.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/components/steps/components/package_policy_input_var_field.tsx index 1deb84143d2a2..c2517c245839d 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/components/steps/components/package_policy_input_var_field.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/components/steps/components/package_policy_input_var_field.tsx @@ -23,11 +23,16 @@ import { EuiFlexGroup, EuiFlexItem, EuiButtonEmpty, + EuiLink, + EuiToolTip, + EuiIcon, } from '@elastic/eui'; import styled from 'styled-components'; import { CodeEditor } from '@kbn/kibana-react-plugin/public'; +import { useStartServices } from '../../../../../../../../hooks'; + import { ExperimentalFeaturesService } from '../../../../../../services'; import { DATASET_VAR_NAME } from '../../../../../../../../../common/constants'; @@ -41,6 +46,16 @@ const FixedHeightDiv = styled.div` height: 300px; `; +const FormRow = styled(EuiFormRow)` + .euiFormRow__label { + flex: 1; + } + + .euiFormRow__fieldWrapper > .euiPanel { + padding: ${(props) => props.theme.eui.euiSizeXS}; + } +`; + interface InputFieldProps { varDef: RegistryVarsEntry; value: any; @@ -125,11 +140,11 @@ export const PackagePolicyInputVarField: React.FunctionComponent : fieldLabel} labelAppend={ isOptional ? ( @@ -138,13 +153,16 @@ export const PackagePolicyInputVarField: React.FunctionComponent - ) : null + ) : undefined } helpText={description && } + fullWidth > {field} - + ); + + return varDef.secret ? {formRow} : formRow; } ); @@ -296,6 +314,53 @@ function getInputComponent({ } } +const SecretFieldWrapper = ({ children }: { children: React.ReactNode }) => { + const { docLinks } = useStartServices(); + + return ( + + {children} + + + + + + + + + + ); +}; + +const SecretFieldLabel = ({ fieldLabel }: { fieldLabel: string }) => { + return ( + <> + + + {fieldLabel} + + + + } + > + + + + + + + + ); +}; + function SecretInputField({ varDef, value, @@ -313,10 +378,12 @@ function SecretInputField({ }: InputComponentProps) { const [editMode, setEditMode] = useState(isEditPage && !value); const valueOnFirstRender = useRef(value); + const lowercaseTitle = varDef.title?.toLowerCase(); + if (isEditPage && !editMode) { return ( - + <> - + ); } diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/edit_package_policy_page/components/upgrade.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/edit_package_policy_page/components/upgrade.tsx index 99eba56ea6a9e..8f10a53afcf2d 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/edit_package_policy_page/components/upgrade.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/edit_package_policy_page/components/upgrade.tsx @@ -24,10 +24,18 @@ import { EuiFlyoutBody, EuiFlyoutHeader, EuiTitle, + EuiSpacer, } from '@elastic/eui'; import styled from 'styled-components'; +import type { + DryRunPackagePolicy, + PackagePolicy, + RegistryVarsEntry, +} from '../../../../../../../common'; + import type { UpgradePackagePolicyDryRunResponse } from '../../../../../../../common/types/rest_spec'; +import { useStartServices } from '../../../../hooks'; const FlyoutBody = styled(EuiFlyoutBody)` .euiFlyoutBody__overflowContent { @@ -35,18 +43,125 @@ const FlyoutBody = styled(EuiFlyoutBody)` } `; +const HasNewSecretsCallOut = ({ newSecrets }: { newSecrets: RegistryVarsEntry[] }) => { + const { docLinks } = useStartServices(); + + return ( + + + Learn more. + + ), + }} + /> + + + + + {newSecrets.map((secret) => ( +
  • {secret.title}
  • + ))} + + ), + }} + /> +
    + ); +}; + +const HasConflictsCallout = ({ + currentPackagePolicy, + proposedUpgradePackagePolicy, + onPreviousConfigurationClick, +}: { + currentPackagePolicy?: PackagePolicy; + proposedUpgradePackagePolicy?: DryRunPackagePolicy; + onPreviousConfigurationClick?: () => void; +}) => { + return ( + + + + + ), + }} + /> + + ); +}; + +const ReadyToUpgradeCallOut = ({ + currentPackagePolicy, + proposedUpgradePackagePolicy, +}: { + currentPackagePolicy?: PackagePolicy; + proposedUpgradePackagePolicy?: DryRunPackagePolicy; +}) => { + return ( + + + + ); +}; + export const UpgradeStatusCallout: React.FunctionComponent<{ dryRunData: UpgradePackagePolicyDryRunResponse; -}> = ({ dryRunData }) => { + newSecrets: RegistryVarsEntry[]; +}> = ({ dryRunData, newSecrets }) => { const [isPreviousVersionFlyoutOpen, setIsPreviousVersionFlyoutOpen] = useState(false); if (!dryRunData) { return null; } - const isReadyForUpgrade = !dryRunData[0].hasErrors; - + const hasNewSecrets = newSecrets.length > 0; const [currentPackagePolicy, proposedUpgradePackagePolicy] = dryRunData[0].diff || []; + const isReadyForUpgrade = currentPackagePolicy && !dryRunData[0].hasErrors; return ( <> @@ -73,48 +188,23 @@ export const UpgradeStatusCallout: React.FunctionComponent<{ )} - {isReadyForUpgrade && currentPackagePolicy ? ( - - - + {isReadyForUpgrade ? ( + ) : ( - - setIsPreviousVersionFlyoutOpen(true)}> - - - ), - }} - /> - + setIsPreviousVersionFlyoutOpen(true)} + /> + )} + {hasNewSecrets && ( + <> + + + )} ); diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/edit_package_policy_page/hooks/use_package_policy.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/edit_package_policy_page/hooks/use_package_policy.tsx index 2f66c590ae3f5..36b1134f9151c 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/edit_package_policy_page/hooks/use_package_policy.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/edit_package_policy_page/hooks/use_package_policy.tsx @@ -99,7 +99,9 @@ export function usePackagePolicyWithRelatedData( policy: { elasticsearch, ...restPackagePolicy }, } = await prepareInputPackagePolicyDataset(packagePolicy); const result = await sendUpdatePackagePolicy(packagePolicyId, restPackagePolicy); + setFormState('SUBMITTED'); + return result; }; // Update package policy validation 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 e3b36999ed0b6..033c083882f45 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,7 +19,6 @@ import { EuiErrorBoundary, } from '@elastic/eui'; -import type { PackageInfo } from '../../../types'; import { useLink, useBreadcrumbs, @@ -55,6 +54,7 @@ import { generateUpdatePackagePolicyDevToolsRequest } from '../services'; import { UpgradeStatusCallout } from './components'; import { usePackagePolicyWithRelatedData, useHistoryBlock } from './hooks'; +import { getNewSecrets } from './utils'; export const EditPackagePolicyPage = memo(() => { const { @@ -91,7 +91,6 @@ export const EditPackagePolicyForm = memo<{ } = useConfig(); const { getHref } = useLink(); - const [] = useState(); const { // data agentPolicy, @@ -117,6 +116,14 @@ export const EditPackagePolicyForm = memo<{ const canWriteIntegrationPolicies = useAuthz().integrations.writeIntegrationPolicies; + const newSecrets = useMemo(() => { + if (!packageInfo) { + return []; + } + + return getNewSecrets({ packageInfo, packagePolicy }); + }, [packageInfo, packagePolicy]); + const policyId = agentPolicy?.id ?? ''; // Retrieve agent count @@ -418,7 +425,7 @@ export const EditPackagePolicyForm = memo<{ )} {isUpgrade && upgradeDryRunData && ( <> - + )} diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/edit_package_policy_page/utils/get_new_secrets.test.ts b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/edit_package_policy_page/utils/get_new_secrets.test.ts new file mode 100644 index 0000000000000..80ae49ed36260 --- /dev/null +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/edit_package_policy_page/utils/get_new_secrets.test.ts @@ -0,0 +1,143 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license 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 { PackageInfo, UpdatePackagePolicy } from '../../../../types'; + +import { getNewSecrets } from './get_new_secrets'; + +describe('getNewSecrets', () => { + it('does not find new secrets when there are no secrets configured', () => { + const packageInfo = { + name: 'mock-package', + title: 'Mock package', + version: '0.0.0', + vars: [ + { + name: 'package-var', + type: 'string', + secret: false, + }, + ], + policy_templates: [ + { + name: 'test-policy-template', + inputs: [ + { + type: 'test-input', + title: 'Test input', + description: 'Test input', + vars: [ + { + name: 'policy-template-var', + type: 'string', + secret: false, + }, + ], + }, + ], + }, + ], + } as unknown as PackageInfo; + + const packagePolicy = { + vars: [ + { + name: 'package-var', + value: 'test', + }, + ], + inputs: [ + { + name: 'test-input', + vars: { + 'policy-template-var': { + value: 'test', + }, + }, + }, + ], + } as unknown as UpdatePackagePolicy; + + expect( + getNewSecrets({ + packageInfo, + packagePolicy, + }) + ).toEqual([]); + }); + + it('finds new secrets when they exist', () => { + const packageInfo = { + name: 'mock-package', + title: 'Mock package', + version: '0.0.0', + vars: [ + { + name: 'package-var', + type: 'string', + secret: true, + }, + ], + policy_templates: [ + { + name: 'test-policy-template', + inputs: [ + { + type: 'test-input', + title: 'Test input', + description: 'Test input', + vars: [ + { + name: 'policy-template-var', + type: 'string', + secret: true, + }, + ], + }, + ], + }, + ], + } as unknown as PackageInfo; + + const packagePolicy = { + vars: [ + { + name: 'package-var', + value: 'test', + }, + ], + inputs: [ + { + name: 'test-input', + vars: { + 'policy-template-var': { + value: 'test', + }, + }, + }, + ], + } as unknown as UpdatePackagePolicy; + + expect( + getNewSecrets({ + packageInfo, + packagePolicy, + }) + ).toEqual([ + { + name: 'package-var', + secret: true, + type: 'string', + }, + { + name: 'policy-template-var', + secret: true, + type: 'string', + }, + ]); + }); +}); diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/edit_package_policy_page/utils/get_new_secrets.ts b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/edit_package_policy_page/utils/get_new_secrets.ts new file mode 100644 index 0000000000000..68f677bbfb894 --- /dev/null +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/edit_package_policy_page/utils/get_new_secrets.ts @@ -0,0 +1,54 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { isInputOnlyPolicyTemplate } from '../../../../../../../common/services'; + +import type { PackageInfo, UpdatePackagePolicy } from '../../../../types'; + +export const getNewSecrets = ({ + packageInfo, + packagePolicy, +}: { + packageInfo: PackageInfo; + packagePolicy: UpdatePackagePolicy; +}) => { + const result = []; + + for (const packageVar of packageInfo.vars ?? []) { + const isVarSecretOnPolicy = packagePolicy.vars?.[packageVar.name]?.value?.isSecretRef; + + if (packageVar.secret && !isVarSecretOnPolicy) { + result.push(packageVar); + } + } + + for (const policyTemplate of packageInfo.policy_templates ?? []) { + if (isInputOnlyPolicyTemplate(policyTemplate)) { + for (const packageVar of policyTemplate.vars ?? []) { + const isVarSecretOnPolicy = + packagePolicy.inputs?.[0]?.vars?.[packageVar.name]?.value?.isSecretRef; + + if (packageVar.secret && !isVarSecretOnPolicy) { + result.push(packageVar); + } + } + } else { + for (const input of policyTemplate.inputs ?? []) { + for (const packageVar of input.vars ?? []) { + const isVarSecretOnPolicy = + packagePolicy.inputs?.[0]?.vars?.[packageVar.name]?.value?.isSecretRef; + + if (packageVar.secret && !isVarSecretOnPolicy) { + result.push(packageVar); + } + } + } + } + } + + return result; +}; diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/edit_package_policy_page/utils/index.ts b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/edit_package_policy_page/utils/index.ts index be01b9834a7dc..5aa227e55bad8 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/edit_package_policy_page/utils/index.ts +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/edit_package_policy_page/utils/index.ts @@ -7,3 +7,4 @@ export * from './has_upgrade_available'; export { fixApmDurationVars } from './fix_apm_duration_vars'; +export * from './get_new_secrets'; diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_list_page/components/agent_upgrade_status.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_list_page/components/agent_upgrade_status.tsx index de9767c2f0b54..572b86d62c73d 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_list_page/components/agent_upgrade_status.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_list_page/components/agent_upgrade_status.tsx @@ -77,7 +77,7 @@ function getStatusComponents(agentUpgradeDetails?: AgentUpgradeDetails) { id="xpack.fleet.agentUpgradeStatusTooltip.upgradeScheduled" defaultMessage="The agent has been instructed to upgrade.{upgradeStartDelay}" values={{ - upgradeStartDelay: getUpgradeStartDelay(agentUpgradeDetails.metadata.scheduled_at), + upgradeStartDelay: getUpgradeStartDelay(agentUpgradeDetails.metadata?.scheduled_at), }} /> ), @@ -97,7 +97,9 @@ function getStatusComponents(agentUpgradeDetails?: AgentUpgradeDetails) { id="xpack.fleet.agentUpgradeStatusTooltip.upgradeDownloading" defaultMessage="Downloading the new agent artifact version{downloadEstimate}." values={{ - downloadEstimate: getDownloadEstimate(agentUpgradeDetails?.metadata.download_percent), + downloadEstimate: getDownloadEstimate( + agentUpgradeDetails?.metadata?.download_percent + ), }} /> ), @@ -202,7 +204,7 @@ function getStatusComponents(agentUpgradeDetails?: AgentUpgradeDetails) { id="xpack.fleet.agentUpgradeStatusTooltip.upgradeFailed" defaultMessage="Upgrade failed: {errorMsg}." values={{ - errorMsg: agentUpgradeDetails?.metadata.error_msg, + errorMsg: agentUpgradeDetails?.metadata?.error_msg, }} /> ), diff --git a/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/overview/details.tsx b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/overview/details.tsx index 8100f07e192ea..f905ac8ca55fa 100644 --- a/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/overview/details.tsx +++ b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/overview/details.tsx @@ -179,6 +179,45 @@ export const Details: React.FC = memo(({ packageInfo }) => { ), }); + let ownerTypeDescription: React.ReactNode; + switch (packageInfo.owner.type) { + case 'community': + ownerTypeDescription = ( + + ); + break; + case 'partner': + ownerTypeDescription = ( + + ); + break; + case 'elastic': + ownerTypeDescription = ( + + ); + break; + } + + if (ownerTypeDescription) { + items.push({ + title: ( + + + + ), + description: ownerTypeDescription, + }); + } + // License details if (packageInfo.licensePath || packageInfo.source?.license || packageInfo.notice) { items.push({ @@ -233,6 +272,7 @@ export const Details: React.FC = memo(({ packageInfo }) => { packageInfo.licensePath, packageInfo.notice, packageInfo.source?.license, + packageInfo.owner.type, packageInfo.version, toggleLicenseModal, toggleNoticeModal, diff --git a/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/overview/overview.tsx b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/overview/overview.tsx index 517c0552f925b..8844a0cb128a5 100644 --- a/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/overview/overview.tsx +++ b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/overview/overview.tsx @@ -327,7 +327,7 @@ export const OverviewPage: React.FC = memo( /> ) : null} - +
    diff --git a/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/confirm_agent_enrollment.tsx b/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/confirm_agent_enrollment.tsx index 173bb2ba0f14a..342f5f8f73249 100644 --- a/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/confirm_agent_enrollment.tsx +++ b/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/confirm_agent_enrollment.tsx @@ -25,6 +25,7 @@ interface Props { onClickViewAgents?: () => void; agentCount: number; showLoading?: boolean; + isLongEnrollment?: boolean; } interface UsePollingAgentCountOptions { @@ -97,6 +98,7 @@ export const ConfirmAgentEnrollment: React.FunctionComponent = ({ onClickViewAgents, agentCount, showLoading = false, + isLongEnrollment = false, }) => { const { getHref } = useLink(); const { application } = useStartServices(); @@ -139,10 +141,17 @@ export const ConfirmAgentEnrollment: React.FunctionComponent = ({ color="primary" iconType={EuiLoadingSpinner} title={ - + isLongEnrollment ? ( + + ) : ( + + ) } /> diff --git a/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/steps/agent_enrollment_confirmation_step.tsx b/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/steps/agent_enrollment_confirmation_step.tsx index 8736e0bf31bc4..fc2ee7d131baf 100644 --- a/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/steps/agent_enrollment_confirmation_step.tsx +++ b/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/steps/agent_enrollment_confirmation_step.tsx @@ -46,6 +46,7 @@ export const AgentEnrollmentConfirmationStep = ({ agentCount, showLoading, poll = true, + isLongEnrollment = false, }: { selectedPolicyId?: string; troubleshootLink: string; @@ -53,6 +54,7 @@ export const AgentEnrollmentConfirmationStep = ({ agentCount: number; poll?: boolean; showLoading?: boolean; + isLongEnrollment?: boolean; }): EuiContainedStepProps => { const isComplete = !!agentCount; return { @@ -71,6 +73,7 @@ export const AgentEnrollmentConfirmationStep = ({ onClickViewAgents={onClickViewAgents} agentCount={agentCount} showLoading={!isComplete || showLoading} + isLongEnrollment={isLongEnrollment} /> ) : ( diff --git a/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/steps/compute_steps.tsx b/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/steps/compute_steps.tsx index 5cc8c109131ae..16dbbb06def8e 100644 --- a/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/steps/compute_steps.tsx +++ b/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/steps/compute_steps.tsx @@ -319,6 +319,7 @@ export const ManagedSteps: React.FunctionComponent = ({ onClickViewAgents, troubleshootLink: link, agentCount: enrolledAgentIds.length, + isLongEnrollment: cloudSecurityIntegration !== undefined, }) ); } diff --git a/x-pack/plugins/fleet/server/index.ts b/x-pack/plugins/fleet/server/index.ts index c928696e6e60a..829e017c67de0 100644 --- a/x-pack/plugins/fleet/server/index.ts +++ b/x-pack/plugins/fleet/server/index.ts @@ -7,8 +7,6 @@ import type { PluginInitializerContext } from '@kbn/core/server'; -import { FleetPlugin } from './plugin'; - export { buildAgentStatusRuntimeField } from './services/agents/build_status_runtime_field'; export type { AgentService, @@ -50,6 +48,7 @@ export type { FleetFileUpdatableFields, } from './services/files/types'; -export const plugin = (initializerContext: PluginInitializerContext) => { +export const plugin = async (initializerContext: PluginInitializerContext) => { + const { FleetPlugin } = await import('./plugin'); return new FleetPlugin(initializerContext); }; diff --git a/x-pack/plugins/fleet/server/routes/agent/upgrade_handler.ts b/x-pack/plugins/fleet/server/routes/agent/upgrade_handler.ts index 78ca30ea1c71f..547fda566a95f 100644 --- a/x-pack/plugins/fleet/server/routes/agent/upgrade_handler.ts +++ b/x-pack/plugins/fleet/server/routes/agent/upgrade_handler.ts @@ -24,6 +24,7 @@ import { getRecentUpgradeInfoForAgent, isAgentUpgradeable, AGENT_UPGRADE_COOLDOWN_IN_MIN, + isAgentUpgrading, } from '../../../common/services'; import { getMaxVersion } from '../../../common/services/get_min_max_version'; import { getAgentById } from '../../services/agents'; @@ -99,6 +100,16 @@ export const postAgentUpgradeHandler: RequestHandler< }, }); } + + if (!force && isAgentUpgrading(agent)) { + return response.customError({ + statusCode: 400, + body: { + message: `agent ${request.params.agentId} is already upgrading`, + }, + }); + } + if (!force && !isAgentUpgradeable(agent, latestAgentVersion, version)) { return response.customError({ statusCode: 400, 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 ad37e03672b74..1f419d71e22d7 100644 --- a/x-pack/plugins/fleet/server/services/agents/agent_service.ts +++ b/x-pack/plugins/fleet/server/services/agents/agent_service.ts @@ -13,6 +13,12 @@ import type { SavedObjectsClientContract, } from '@kbn/core/server'; +import type { AggregationsAggregationContainer } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; + +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; + +import type { SortResults } from '@elastic/elasticsearch/lib/api/types'; + import type { AgentStatus, ListWithKuery } from '../../types'; import type { Agent, GetAgentStatusResponse } from '../../../common/types'; @@ -72,12 +78,17 @@ export interface AgentClient { listAgents( options: ListWithKuery & { showInactive: boolean; + aggregations?: Record; + searchAfter?: SortResults; + pitId?: string; + getStatusSummary?: boolean; } ): Promise<{ agents: Agent[]; total: number; page: number; perPage: number; + aggregations?: Record; }>; /** @@ -99,6 +110,7 @@ class AgentClientImpl implements AgentClient { public async listAgents( options: ListWithKuery & { showInactive: boolean; + aggregations?: Record; } ) { await this.#runPreflight(); diff --git a/x-pack/plugins/fleet/server/services/agents/crud.ts b/x-pack/plugins/fleet/server/services/agents/crud.ts index 1521a19f51af1..7ad50c8d962c1 100644 --- a/x-pack/plugins/fleet/server/services/agents/crud.ts +++ b/x-pack/plugins/fleet/server/services/agents/crud.ts @@ -11,6 +11,8 @@ import type { SavedObjectsClientContract, ElasticsearchClient } from '@kbn/core/ import type { KueryNode } from '@kbn/es-query'; import { fromKueryExpression, toElasticsearchQuery } from '@kbn/es-query'; +import type { AggregationsAggregationContainer } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; + import type { AgentSOAttributes, Agent, ListWithKuery } from '../../types'; import { appContextService, agentPolicyService } from '..'; import type { AgentStatus, FleetServerAgent } from '../../../common/types'; @@ -211,6 +213,7 @@ export async function getAgentsByKuery( sortOrder?: 'asc' | 'desc'; pitId?: string; searchAfter?: SortResults; + aggregations?: Record; } ): Promise<{ agents: Agent[]; @@ -218,6 +221,7 @@ export async function getAgentsByKuery( page: number; perPage: number; statusSummary?: Record; + aggregations?: Record; }> { const { page = 1, @@ -230,6 +234,7 @@ export async function getAgentsByKuery( showUpgradeable, searchAfter, pitId, + aggregations, } = options; const filters = []; @@ -263,8 +268,27 @@ export async function getAgentsByKuery( unenrolling: 0, }; - const queryAgents = async (from: number, size: number) => - esClient.search< + const queryAgents = async (from: number, size: number) => { + const aggs = { + ...(aggregations || getStatusSummary + ? { + aggs: { + ...(aggregations ? aggregations : {}), + ...(getStatusSummary + ? { + status: { + terms: { + field: 'status', + }, + }, + } + : {}), + }, + } + : {}), + }; + + return esClient.search< FleetServerAgent, { status: { buckets: Array<{ key: AgentStatus; doc_count: number }> } } >({ @@ -288,8 +312,9 @@ export async function getAgentsByKuery( ignore_unavailable: true, }), ...(pitId && searchAfter ? { search_after: searchAfter, from: 0 } : {}), - ...(getStatusSummary && { aggs: { status: { terms: { field: 'status' } } } }), + ...aggs, }); + }; let res; try { res = await queryAgents((page - 1) * perPage, perPage); @@ -331,6 +356,7 @@ export async function getAgentsByKuery( total, page, perPage, + ...(aggregations ? { aggregations: res.aggregations } : {}), ...(getStatusSummary ? { statusSummary } : {}), }; } diff --git a/x-pack/plugins/fleet/server/services/agents/upgrade.test.ts b/x-pack/plugins/fleet/server/services/agents/upgrade.test.ts index 2e90a27a3bf24..8327e09842f8f 100644 --- a/x-pack/plugins/fleet/server/services/agents/upgrade.test.ts +++ b/x-pack/plugins/fleet/server/services/agents/upgrade.test.ts @@ -153,10 +153,10 @@ describe('getRollingUpgradeOptions', () => { }); }); - it('should set min expiration for no duration', () => { + it('should set a very long expiration (1 month) for no duration', () => { const options = getRollingUpgradeOptions('2023-01-06T00:00:00Z'); expect(options).toEqual({ - expiration: '2023-01-06T02:00:00.000Z', + expiration: '2023-02-05T00:00:00.000Z', minimum_execution_duration: 7200, start_time: '2023-01-06T00:00:00Z', }); diff --git a/x-pack/plugins/fleet/server/services/agents/upgrade_action_runner.ts b/x-pack/plugins/fleet/server/services/agents/upgrade_action_runner.ts index b6ab67e5fb5e3..157eaa688c746 100644 --- a/x-pack/plugins/fleet/server/services/agents/upgrade_action_runner.ts +++ b/x-pack/plugins/fleet/server/services/agents/upgrade_action_runner.ts @@ -76,7 +76,12 @@ export async function upgradeBatch( const latestAgentVersion = await getLatestAvailableVersion(); const upgradeableResults = await Promise.allSettled( agentsToCheckUpgradeable.map(async (agent) => { - // Filter out agents currently unenrolling, unenrolled, recently upgraded or not upgradeable b/c of version check + // Filter out agents that are: + // - currently unenrolling + // - unenrolled + // - recently upgraded + // - currently upgrading + // - upgradeable b/c of version check const isNotAllowed = getRecentUpgradeInfoForAgent(agent).hasBeenUpgradedRecently || (!options.force && !isAgentUpgradeable(agent, latestAgentVersion, options.version)); @@ -173,6 +178,7 @@ export async function upgradeBatch( } export const MINIMUM_EXECUTION_DURATION_SECONDS = 60 * 60 * 2; // 2h +export const EXPIRATION_DURATION_SECONDS = 60 * 60 * 24 * 30; // 1 month export const getRollingUpgradeOptions = (startTime?: string, upgradeDurationSeconds?: number) => { const now = new Date().toISOString(); @@ -199,13 +205,12 @@ export const getRollingUpgradeOptions = (startTime?: string, upgradeDurationSeco }; } // Schedule without rolling upgrade (Immediately after start_time) + // Expiration time is set to a very long value (1 month) to allow upgrading agents staying offline for long time if (startTime && !upgradeDurationSeconds) { return { start_time: startTime ?? now, minimum_execution_duration: MINIMUM_EXECUTION_DURATION_SECONDS, - expiration: moment(startTime) - .add(MINIMUM_EXECUTION_DURATION_SECONDS, 'seconds') - .toISOString(), + expiration: moment(startTime).add(EXPIRATION_DURATION_SECONDS, 'seconds').toISOString(), }; } else { // Regular bulk upgrade (non scheduled, non rolling) diff --git a/x-pack/plugins/fleet/server/services/epm/packages/bundled_packages.ts b/x-pack/plugins/fleet/server/services/epm/packages/bundled_packages.ts index decd5e977506c..7078761a4a583 100644 --- a/x-pack/plugins/fleet/server/services/epm/packages/bundled_packages.ts +++ b/x-pack/plugins/fleet/server/services/epm/packages/bundled_packages.ts @@ -8,7 +8,7 @@ import fs from 'fs/promises'; import path from 'path'; -import type { BundledPackage } from '../../../types'; +import type { BundledPackage, Installation } from '../../../types'; import { FleetError } from '../../../errors'; import { appContextService } from '../../app_context'; import { splitPkgKey, pkgToPkgKey } from '../registry'; @@ -57,24 +57,33 @@ export async function getBundledPackages(): Promise { } } +export async function getBundledPackageForInstallation( + installation: Installation +): Promise { + const bundledPackages = await getBundledPackages(); + + return bundledPackages.find( + (bundledPkg: BundledPackage) => + bundledPkg.name === installation.name && bundledPkg.version === installation.version + ); +} + export async function getBundledPackageByPkgKey( pkgKey: string ): Promise { const bundledPackages = await getBundledPackages(); - const bundledPackage = bundledPackages.find((pkg) => { + + return bundledPackages.find((pkg) => { if (pkgKey.includes('-')) { return pkgToPkgKey(pkg) === pkgKey; } else { return pkg.name === pkgKey; } }); - - return bundledPackage; } export async function getBundledPackageByName(name: string): Promise { const bundledPackages = await getBundledPackages(); - const bundledPackage = bundledPackages.find((pkg) => pkg.name === name); - return bundledPackage; + return bundledPackages.find((pkg) => pkg.name === name); } diff --git a/x-pack/plugins/fleet/server/services/epm/packages/install.test.ts b/x-pack/plugins/fleet/server/services/epm/packages/install.test.ts index d21e023ce7cdd..f3e464d7a9f67 100644 --- a/x-pack/plugins/fleet/server/services/epm/packages/install.test.ts +++ b/x-pack/plugins/fleet/server/services/epm/packages/install.test.ts @@ -282,7 +282,7 @@ describe('install', () => { expect(response.error).toBeUndefined(); expect(install._installPackage).toHaveBeenCalledWith( - expect.objectContaining({ installSource: 'upload' }) + expect.objectContaining({ installSource: 'bundled' }) ); }); diff --git a/x-pack/plugins/fleet/server/services/epm/packages/install.ts b/x-pack/plugins/fleet/server/services/epm/packages/install.ts index ffd1dfe6379c2..3a7fc78096159 100644 --- a/x-pack/plugins/fleet/server/services/epm/packages/install.ts +++ b/x-pack/plugins/fleet/server/services/epm/packages/install.ts @@ -328,6 +328,7 @@ interface InstallUploadedArchiveParams { authorizationHeader?: HTTPAuthorizationHeader | null; ignoreMappingUpdateErrors?: boolean; skipDataStreamRollover?: boolean; + isBundledPackage?: boolean; } function getTelemetryEvent(pkgName: string, pkgVersion: string): PackageUpdateEvent { @@ -460,7 +461,7 @@ function getElasticSubscription(packageInfo: ArchivePackage) { async function installPackageCommon(options: { pkgName: string; pkgVersion: string; - installSource: 'registry' | 'upload' | 'custom'; + installSource: InstallSource; installedPkg?: SavedObject; installType: InstallType; savedObjectsClient: SavedObjectsClientContract; @@ -638,10 +639,11 @@ async function installPackageByUpload({ authorizationHeader, ignoreMappingUpdateErrors, skipDataStreamRollover, + isBundledPackage, }: InstallUploadedArchiveParams): Promise { // if an error happens during getInstallType, report that we don't know let installType: InstallType = 'unknown'; - const installSource = 'upload'; + const installSource = isBundledPackage ? 'bundled' : 'upload'; try { const { packageInfo } = await generatePackageInfoFromArchiveBuffer(archiveBuffer, contentType); const pkgName = packageInfo.name; @@ -747,6 +749,7 @@ export async function installPackage(args: InstallPackageParams): Promise; +const mockedInstallPackage = jest.mocked(installPackage); +const mockedGetBundledPackageForInstallation = jest.mocked(getBundledPackageForInstallation); describe('reinstallPackageForInstallation', () => { beforeEach(() => { mockedInstallPackage.mockReset(); + mockedGetBundledPackageForInstallation.mockImplementation(async ({ name }) => { + if (name === 'test_bundled') { + return {} as any; + } + }); }); it('should throw an error for uploaded package', async () => { const soClient = savedObjectsClientMock.create(); @@ -67,7 +75,7 @@ describe('reinstallPackageForInstallation', () => { esClient, installation: { install_source: 'bundled', - name: 'test', + name: 'test_bundled', version: '1.0.0', } as Installation, }) @@ -76,7 +84,32 @@ describe('reinstallPackageForInstallation', () => { expect(mockedInstallPackage).toHaveBeenCalledWith( expect.objectContaining({ installSource: 'registry', - pkgkey: 'test-1.0.0', + pkgkey: 'test_bundled-1.0.0', + force: true, + }) + ); + }); + + // Pre 8.12.0 bundled package install where saved with install_source_upload + it('should install bundled package saved with install_source:upload ', async () => { + const soClient = savedObjectsClientMock.create(); + const esClient = elasticsearchServiceMock.createInternalClient(); + await expect( + reinstallPackageForInstallation({ + soClient, + esClient, + installation: { + install_source: 'upload', + name: 'test_bundled', + version: '1.0.0', + } as Installation, + }) + ); + + expect(mockedInstallPackage).toHaveBeenCalledWith( + expect.objectContaining({ + installSource: 'registry', + pkgkey: 'test_bundled-1.0.0', force: true, }) ); diff --git a/x-pack/plugins/fleet/server/services/epm/packages/reinstall.ts b/x-pack/plugins/fleet/server/services/epm/packages/reinstall.ts index 6f6ed35f4974b..d2672b6089819 100644 --- a/x-pack/plugins/fleet/server/services/epm/packages/reinstall.ts +++ b/x-pack/plugins/fleet/server/services/epm/packages/reinstall.ts @@ -11,6 +11,8 @@ import { DEFAULT_SPACE_ID } from '@kbn/spaces-plugin/common/constants'; import type { Installation } from '../../../types'; import { pkgToPkgKey } from '../registry'; +import { getBundledPackageForInstallation } from './bundled_packages'; + import { installPackage } from './install'; export async function reinstallPackageForInstallation({ @@ -22,9 +24,18 @@ export async function reinstallPackageForInstallation({ esClient: ElasticsearchClient; installation: Installation; }) { - if (installation.install_source === 'upload') { - throw new Error('Cannot reinstall an uploaded package'); + if (installation.install_source === 'upload' || installation.install_source === 'bundled') { + // If there is a matching bundled package + const matchingBundledPackage = await getBundledPackageForInstallation(installation); + if (!matchingBundledPackage) { + if (installation.install_source === 'bundled') { + throw new Error(`Cannot reinstall: ${installation.name}, bundled package not found`); + } else { + throw new Error('Cannot reinstall an uploaded package'); + } + } } + return installPackage({ // If the package is bundled reinstall from the registry will still use the bundled package. installSource: 'registry', diff --git a/x-pack/plugins/fleet/server/services/setup.ts b/x-pack/plugins/fleet/server/services/setup.ts index d83e1424c54c4..270cfefb56a82 100644 --- a/x-pack/plugins/fleet/server/services/setup.ts +++ b/x-pack/plugins/fleet/server/services/setup.ts @@ -14,11 +14,7 @@ import { DEFAULT_SPACE_ID } from '@kbn/spaces-plugin/common/constants'; import { AUTO_UPDATE_PACKAGES } from '../../common/constants'; import type { PreconfigurationError } from '../../common/constants'; -import type { - DefaultPackagesInstallationError, - BundledPackage, - Installation, -} from '../../common/types'; +import type { DefaultPackagesInstallationError } from '../../common/types'; import { SO_SEARCH_LIMIT } from '../constants'; @@ -45,7 +41,6 @@ import { getInstallations, reinstallPackageForInstallation } from './epm/package import { isPackageInstalled } from './epm/packages/install'; import type { UpgradeManagedPackagePoliciesResult } from './managed_package_policies'; import { upgradeManagedPackagePolicies } from './managed_package_policies'; -import { getBundledPackages } from './epm/packages'; import { upgradePackageInstallVersion } from './setup/upgrade_package_install_version'; import { upgradeAgentPolicySchemaVersion } from './setup/upgrade_agent_policy_schema_version'; import { migrateSettingsToFleetServerHost } from './fleet_server_host'; @@ -219,24 +214,9 @@ export async function ensureFleetGlobalEsAssets( if (assetResults.some((asset) => asset.isCreated)) { // Update existing index template const installedPackages = await getInstallations(soClient); - const bundledPackages = await getBundledPackages(); - const findMatchingBundledPkg = (pkg: Installation) => - bundledPackages.find( - (bundledPkg: BundledPackage) => - bundledPkg.name === pkg.name && bundledPkg.version === pkg.version - ); await pMap( installedPackages.saved_objects, async ({ attributes: installation }) => { - if (installation.install_source !== 'registry') { - const matchingBundledPackage = findMatchingBundledPkg(installation); - if (!matchingBundledPackage) { - logger.error( - `Package needs to be manually reinstalled ${installation.name} after installing Fleet global assets` - ); - return; - } - } await reinstallPackageForInstallation({ soClient, esClient, diff --git a/x-pack/plugins/fleet/server/services/setup/upgrade_package_install_version.test.ts b/x-pack/plugins/fleet/server/services/setup/upgrade_package_install_version.test.ts new file mode 100644 index 0000000000000..102baa8f1d6a4 --- /dev/null +++ b/x-pack/plugins/fleet/server/services/setup/upgrade_package_install_version.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 { + elasticsearchServiceMock, + loggingSystemMock, + savedObjectsClientMock, +} from '@kbn/core/server/mocks'; + +import { reinstallPackageForInstallation } from '../epm/packages'; + +import { upgradePackageInstallVersion } from './upgrade_package_install_version'; + +jest.mock('../epm/packages'); + +const mockedReinstallPackageForInstallation = jest.mocked(reinstallPackageForInstallation); + +describe('upgradePackageInstallVersion', () => { + beforeEach(() => { + mockedReinstallPackageForInstallation.mockReset(); + mockedReinstallPackageForInstallation.mockResolvedValue({} as any); + }); + it('should upgrade outdated package version', async () => { + const logger = loggingSystemMock.createLogger(); + const esClient = elasticsearchServiceMock.createInternalClient(); + const soClient = savedObjectsClientMock.create(); + + soClient.find.mockResolvedValue({ + total: 2, + saved_objects: [ + { + attributes: { name: 'test1' }, + }, + { + attributes: { name: 'test2' }, + }, + ], + } as any); + + await upgradePackageInstallVersion({ + esClient, + soClient, + logger, + }); + + expect(mockedReinstallPackageForInstallation).toBeCalledTimes(2); + expect(mockedReinstallPackageForInstallation).toBeCalledWith( + expect.objectContaining({ + installation: expect.objectContaining({ name: 'test1' }), + }) + ); + expect(mockedReinstallPackageForInstallation).toBeCalledWith( + expect.objectContaining({ + installation: expect.objectContaining({ name: 'test2' }), + }) + ); + + expect(logger.warn).not.toBeCalled(); + expect(logger.error).not.toBeCalled(); + }); + + it('should log at error level when an error happens while reinstalling package', async () => { + const logger = loggingSystemMock.createLogger(); + const esClient = elasticsearchServiceMock.createInternalClient(); + const soClient = savedObjectsClientMock.create(); + + mockedReinstallPackageForInstallation.mockRejectedValue(new Error('test error')); + soClient.find.mockResolvedValue({ + total: 2, + saved_objects: [ + { + attributes: { name: 'test1' }, + }, + ], + } as any); + + await upgradePackageInstallVersion({ + esClient, + soClient, + logger, + }); + + expect(logger.error).toBeCalled(); + }); + + it('should log a warn level when an error happens while reinstalling an uploaded package', async () => { + const logger = loggingSystemMock.createLogger(); + const esClient = elasticsearchServiceMock.createInternalClient(); + const soClient = savedObjectsClientMock.create(); + + mockedReinstallPackageForInstallation.mockRejectedValue(new Error('test error')); + soClient.find.mockResolvedValue({ + total: 2, + saved_objects: [ + { + attributes: { name: 'test1', install_source: 'upload' }, + }, + ], + } as any); + + await upgradePackageInstallVersion({ + esClient, + soClient, + logger, + }); + + expect(logger.warn).toBeCalled(); + }); +}); diff --git a/x-pack/plugins/fleet/server/services/setup/upgrade_package_install_version.ts b/x-pack/plugins/fleet/server/services/setup/upgrade_package_install_version.ts index cceb293b165bd..db85e269dc345 100644 --- a/x-pack/plugins/fleet/server/services/setup/upgrade_package_install_version.ts +++ b/x-pack/plugins/fleet/server/services/setup/upgrade_package_install_version.ts @@ -35,7 +35,6 @@ export async function upgradePackageInstallVersion({ logger: Logger; }) { const res = await findOutdatedInstallations(soClient); - if (res.total === 0) { return; } @@ -44,18 +43,20 @@ export async function upgradePackageInstallVersion({ res.saved_objects, ({ attributes: installation }) => { // Uploaded package cannot be reinstalled - if (installation.install_source === 'upload') { - logger.warn(`Uploaded package needs to be manually reinstalled ${installation.name}.`); - return; - } return reinstallPackageForInstallation({ soClient, esClient, installation, }).catch((err: Error) => { - logger.error( - `Package needs to be manually reinstalled ${installation.name} updating install_version failed. ${err.message}` - ); + if (installation.install_source === 'upload') { + logger.warn( + `Uploaded package needs to be manually reinstalled ${installation.name}. ${err.message}` + ); + } else { + logger.error( + `Package needs to be manually reinstalled ${installation.name} updating install_version failed. ${err.message}` + ); + } }); }, { concurrency: 10 } diff --git a/x-pack/plugins/global_search/server/index.ts b/x-pack/plugins/global_search/server/index.ts index 107486c857f94..fb658271a1706 100644 --- a/x-pack/plugins/global_search/server/index.ts +++ b/x-pack/plugins/global_search/server/index.ts @@ -6,11 +6,7 @@ */ import { PluginInitializer } from '@kbn/core/server'; -import { - GlobalSearchPlugin, - GlobalSearchPluginSetupDeps, - GlobalSearchPluginStartDeps, -} from './plugin'; +import { GlobalSearchPluginSetupDeps, GlobalSearchPluginStartDeps } from './plugin'; import { GlobalSearchPluginSetup, GlobalSearchPluginStart } from './types'; export const plugin: PluginInitializer< @@ -18,7 +14,10 @@ export const plugin: PluginInitializer< GlobalSearchPluginStart, GlobalSearchPluginSetupDeps, GlobalSearchPluginStartDeps -> = (context) => new GlobalSearchPlugin(context); +> = async (context) => { + const { GlobalSearchPlugin } = await import('./plugin'); + return new GlobalSearchPlugin(context); +}; export { config } from './config'; diff --git a/x-pack/plugins/global_search_providers/server/index.ts b/x-pack/plugins/global_search_providers/server/index.ts index 92b3a4347492e..7205361566b86 100644 --- a/x-pack/plugins/global_search_providers/server/index.ts +++ b/x-pack/plugins/global_search_providers/server/index.ts @@ -6,7 +6,14 @@ */ import { PluginInitializer } from '@kbn/core/server'; -import { GlobalSearchProvidersPlugin, GlobalSearchProvidersPluginSetupDeps } from './plugin'; +import type { GlobalSearchProvidersPluginSetupDeps } from './plugin'; -export const plugin: PluginInitializer<{}, {}, GlobalSearchProvidersPluginSetupDeps, {}> = () => - new GlobalSearchProvidersPlugin(); +export const plugin: PluginInitializer< + {}, + {}, + GlobalSearchProvidersPluginSetupDeps, + {} +> = async () => { + const { GlobalSearchProvidersPlugin } = await import('./plugin'); + return new GlobalSearchProvidersPlugin(); +}; diff --git a/x-pack/plugins/graph/server/index.ts b/x-pack/plugins/graph/server/index.ts index 86dca6c119604..46877645a8503 100644 --- a/x-pack/plugins/graph/server/index.ts +++ b/x-pack/plugins/graph/server/index.ts @@ -8,10 +8,11 @@ import { PluginConfigDescriptor, PluginInitializerContext } from '@kbn/core/server'; import { configSchema, ConfigSchema } from '../config'; -import { GraphPlugin } from './plugin'; -export const plugin = (initializerContext: PluginInitializerContext) => - new GraphPlugin(initializerContext); +export const plugin = async (initializerContext: PluginInitializerContext) => { + const { GraphPlugin } = await import('./plugin'); + return new GraphPlugin(initializerContext); +}; export const config: PluginConfigDescriptor = { exposeToBrowser: { diff --git a/x-pack/plugins/grokdebugger/server/index.js b/x-pack/plugins/grokdebugger/server/index.js index 418959762f9ab..fcc537e64e34e 100644 --- a/x-pack/plugins/grokdebugger/server/index.js +++ b/x-pack/plugins/grokdebugger/server/index.js @@ -5,9 +5,10 @@ * 2.0. */ -import { Plugin, config } from './plugin'; +import { config } from './plugin'; -export function plugin() { +export async function plugin() { + const { Plugin } = await import('./plugin'); return new Plugin(); } diff --git a/x-pack/plugins/index_lifecycle_management/__jest__/__snapshots__/extend_index_management.test.tsx.snap b/x-pack/plugins/index_lifecycle_management/__jest__/__snapshots__/extend_index_management.test.tsx.snap index b67ddac26fd7e..3a85403c5649a 100644 --- a/x-pack/plugins/index_lifecycle_management/__jest__/__snapshots__/extend_index_management.test.tsx.snap +++ b/x-pack/plugins/index_lifecycle_management/__jest__/__snapshots__/extend_index_management.test.tsx.snap @@ -94,121 +94,284 @@ Array [ ] `; -exports[`extend index management ilm summary extension should return extension when index has lifecycle error 1`] = ` -Array [ -

    - Index lifecycle management -

    , -
    , -
    -

    -

    -
    -
    - illegal_argument_exception: setting [index.lifecycle.rollover_alias] for index [testy3] is empty or not defined -
    -
    , -
    , +exports[`extend index management ilm summary extension should render a phase definition panel when lifecycle has phase definition 1`] = ` +
    + +
    - - Lifecycle policy - + Policy name
    - +
    + Current phase +
    +
    + - testy - + + + Hot + + +
    - - Current action - + Current action
    - rollover + + rollover +
    - - Failed step - + Current action time
    - check-rollover-ready + 2018-12-07 13:02:55 +
    +
    + Current step +
    +
    + + test +
    +
    +
    +
    +

    + Current phase definition +

    +
    +
    +
    +
    +          
    +            {
    +  "policy": "testy",
    +  "phase_definition": {
    +    "min_age": "0s",
    +    "actions": {
    +      "rollover": {
    +        "max_size": "1gb"
    +      }
    +    }
    +  },
    +  "version": 1,
    +  "modified_date_in_millis": 1544031699844
    +}
    +          
    +        
    +
    +
    +
    +
    +`; + +exports[`extend index management ilm summary extension should render a step info panel when lifecycle is waiting for a step completion 1`] = ` +
    +
    +
    + +
    - - Current phase - + Policy name +
    +
    + testy +
    +
    + Current phase +
    +
    + + + + Hot + + + +
    +
    + Current action
    - hot + + rollover +
    - - Current action time - + Current action time
    - - Phase definition - + Current step
    -
    -
    - -
    -
    + + test +
    -
    , -] +
    +
    +
    +
    +

    + Current step info +

    +
    +
    +
    +            
    +              {
    +  "message": "Waiting for all shard copies to be active",
    +  "shards_left_to_allocate": -1,
    +  "all_shards_active": false,
    +  "number_of_replicas": 2
    +}
    +            
    +          
    +
    +
    +
    +
    +
    +
    `; -exports[`extend index management ilm summary extension should return extension when index has lifecycle policy 1`] = ` -Array [ -

    - Index lifecycle management -

    , -
    , +exports[`extend index management ilm summary extension should render an error panel when index has lifecycle error 1`] = ` +
    + +
    - - Lifecycle policy - + Policy name
    - +
    + Current phase +
    +
    + - testy - + + + Hot + + + +
    +
    + Current action +
    +
    + + rollover +
    - - Current action - + Current action time
    - complete + 2018-12-07 13:02:55
    - - Failed step - + Current step
    - - + + ERROR +
    +
    +
    +
    +

    + Lifecycle error +

    +
    +
    +
    +            
    +              {
    +  "failed_step": "check-rollover-ready",
    +  "step_info": {
    +    "type": "illegal_argument_exception",
    +    "reason": "setting [index.lifecycle.rollover_alias] for index [testy3] is empty or not defined"
    +  }
    +}
    +            
    +          
    +
    +
    +
    +
    +
    +
    +`; + +exports[`extend index management ilm summary extension should render the tab when index has lifecycle policy 1`] = ` +
    +
    +
    + +
    - - Current phase - + Policy name +
    +
    + testy +
    +
    + Current phase +
    +
    + + + + new + + + +
    +
    + Current action
    - new + + complete +
    - - Current action time - + Current action time
    2018-12-07 13:02:55
    +
    + Current step +
    +
    + + complete + +
    -
    , -] +
    +
    +
    `; exports[`extend index management remove lifecycle action extension should return extension when all indices have lifecycle policy 1`] = ` diff --git a/x-pack/plugins/index_lifecycle_management/__jest__/extend_index_management.test.tsx b/x-pack/plugins/index_lifecycle_management/__jest__/extend_index_management.test.tsx index 244536ad4afef..e26000bcacc7d 100644 --- a/x-pack/plugins/index_lifecycle_management/__jest__/extend_index_management.test.tsx +++ b/x-pack/plugins/index_lifecycle_management/__jest__/extend_index_management.test.tsx @@ -22,6 +22,7 @@ import { init as initHttp } from '../public/application/services/http'; import { init as initUiMetric } from '../public/application/services/ui_metric'; import { indexLifecycleTab } from '../public/extend_index_management/components/index_lifecycle_summary'; import { Index } from '@kbn/index-management-plugin/common'; +import { findTestSubject } from '@elastic/eui/lib/test'; const { httpSetup } = init(); @@ -111,6 +112,33 @@ const indexWithLifecycleError: Index = { type: 'illegal_argument_exception', reason: 'setting [index.lifecycle.rollover_alias] for index [testy3] is empty or not defined', }, + }, +}; +const indexWithLifecyclePhaseDefinition: Index = { + health: 'yellow', + status: 'open', + name: 'testy3', + uuid: 'XL11TLa3Tvq298_dMUzLHQ', + primary: 1, + replica: 1, + documents: 2, + documents_deleted: 0, + size: '6.5kb', + primary_size: '6.5kb', + aliases: 'none', + isFrozen: false, + hidden: false, + ilm: { + index: 'testy3', + managed: true, + policy: 'testy', + lifecycle_date_millis: 1544020872361, + phase: 'hot', + phase_time_millis: 1544187775891, + action: 'rollover', + action_time_millis: 1544187775891, + step: 'test', + step_time_millis: 1544187776208, phase_execution: { policy: 'testy', // @ts-expect-error ILM type is incorrect https://github.com/elastic/elasticsearch-specification/issues/2326 @@ -120,6 +148,39 @@ const indexWithLifecycleError: Index = { }, }, }; +const indexWithLifecycleWaitingStep: Index = { + health: 'yellow', + status: 'open', + name: 'testy3', + uuid: 'XL11TLa3Tvq298_dMUzLHQ', + primary: 1, + replica: 1, + documents: 2, + documents_deleted: 0, + size: '6.5kb', + primary_size: '6.5kb', + aliases: 'none', + isFrozen: false, + hidden: false, + ilm: { + index: 'testy3', + managed: true, + policy: 'testy', + lifecycle_date_millis: 1544020872361, + phase: 'hot', + phase_time_millis: 1544187775891, + action: 'rollover', + action_time_millis: 1544187775891, + step: 'test', + step_time_millis: 1544187776208, + step_info: { + message: 'Waiting for all shard copies to be active', + shards_left_to_allocate: -1, + all_shards_active: false, + number_of_replicas: 2, + }, + }, +}; moment.tz.setDefault('utc'); @@ -245,6 +306,11 @@ describe('extend index management', () => { describe('ilm summary extension', () => { const IlmComponent = indexLifecycleTab.renderTabContent; + const policyPropertiesPanel = 'policyPropertiesPanel'; + const policyStepPanel = 'policyStepPanel'; + const policyErrorPanel = 'policyErrorPanel'; + const phaseDefinitionPanel = 'phaseDefinitionPanel'; + test('should not render the tab when index has no index lifecycle policy', () => { const shouldRenderTab = indexLifecycleTab.shouldRenderTab && @@ -254,22 +320,58 @@ describe('extend index management', () => { expect(shouldRenderTab).toBeFalsy(); }); - test('should return extension when index has lifecycle policy', () => { + test('should render the tab when index has lifecycle policy', () => { + const shouldRenderTab = + indexLifecycleTab.shouldRenderTab && + indexLifecycleTab.shouldRenderTab({ + index: indexWithLifecyclePolicy, + }); + expect(shouldRenderTab).toBeTruthy(); const ilmContent = ( ); - expect(ilmContent).toBeDefined(); const rendered = mountWithIntl(ilmContent); expect(rendered.render()).toMatchSnapshot(); + expect(findTestSubject(rendered, policyPropertiesPanel).exists()).toBeTruthy(); + expect(findTestSubject(rendered, phaseDefinitionPanel).exists()).toBeFalsy(); + expect(findTestSubject(rendered, policyStepPanel).exists()).toBeFalsy(); + expect(findTestSubject(rendered, policyErrorPanel).exists()).toBeFalsy(); }); - test('should return extension when index has lifecycle error', () => { + test('should render an error panel when index has lifecycle error', () => { const ilmContent = ( ); - expect(ilmContent).toBeDefined(); const rendered = mountWithIntl(ilmContent); expect(rendered.render()).toMatchSnapshot(); + expect(findTestSubject(rendered, policyPropertiesPanel).exists()).toBeTruthy(); + expect(findTestSubject(rendered, phaseDefinitionPanel).exists()).toBeFalsy(); + expect(findTestSubject(rendered, policyStepPanel).exists()).toBeFalsy(); + expect(findTestSubject(rendered, policyErrorPanel).exists()).toBeTruthy(); + }); + + test('should render a phase definition panel when lifecycle has phase definition', () => { + const ilmContent = ( + + ); + const rendered = mountWithIntl(ilmContent); + expect(rendered.render()).toMatchSnapshot(); + expect(findTestSubject(rendered, policyPropertiesPanel).exists()).toBeTruthy(); + expect(findTestSubject(rendered, phaseDefinitionPanel).exists()).toBeTruthy(); + expect(findTestSubject(rendered, policyStepPanel).exists()).toBeFalsy(); + expect(findTestSubject(rendered, policyErrorPanel).exists()).toBeFalsy(); + }); + + test('should render a step info panel when lifecycle is waiting for a step completion', () => { + const ilmContent = ( + + ); + const rendered = mountWithIntl(ilmContent); + expect(rendered.render()).toMatchSnapshot(); + expect(findTestSubject(rendered, policyPropertiesPanel).exists()).toBeTruthy(); + expect(findTestSubject(rendered, phaseDefinitionPanel).exists()).toBeFalsy(); + expect(findTestSubject(rendered, policyStepPanel).exists()).toBeTruthy(); + expect(findTestSubject(rendered, policyErrorPanel).exists()).toBeFalsy(); }); }); diff --git a/x-pack/plugins/index_lifecycle_management/public/extend_index_management/components/index_lifecycle_summary.tsx b/x-pack/plugins/index_lifecycle_management/public/extend_index_management/components/index_lifecycle_summary.tsx index 162457479788f..0afe886bf1706 100644 --- a/x-pack/plugins/index_lifecycle_management/public/extend_index_management/components/index_lifecycle_summary.tsx +++ b/x-pack/plugins/index_lifecycle_management/public/extend_index_management/components/index_lifecycle_summary.tsx @@ -5,240 +5,241 @@ * 2.0. */ -import React, { FunctionComponent, Fragment, useState } from 'react'; +import React, { FunctionComponent } from 'react'; import moment from 'moment-timezone'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n-react'; +import { css } from '@emotion/react'; import { - EuiCallOut, EuiCodeBlock, - EuiFlexGroup, + EuiLink, EuiFlexItem, - EuiDescriptionList, - EuiDescriptionListTitle, - EuiDescriptionListDescription, + EuiFlexGroup, + EuiPanel, + EuiText, EuiSpacer, - EuiTitle, - EuiLink, - EuiPopover, - EuiPopoverTitle, + EuiDescriptionList, + EuiBadgeProps, + EuiBadge, + EuiCode, } from '@elastic/eui'; +import { euiThemeVars } from '@kbn/ui-theme'; import { ApplicationStart } from '@kbn/core/public'; import { Index } from '@kbn/index-management-plugin/common'; import { IndexDetailsTab } from '@kbn/index-management-plugin/common/constants'; import { IlmExplainLifecycleLifecycleExplainManaged } from '@elastic/elasticsearch/lib/api/types'; +import { Phase } from '../../../common/types'; import { getPolicyEditPath } from '../../application/services/navigation'; -const getHeaders = (): Array<[keyof IlmExplainLifecycleLifecycleExplainManaged, string]> => { - return [ - [ - 'policy', - i18n.translate( - 'xpack.indexLifecycleMgmt.indexLifecycleMgmtSummary.headers.lifecyclePolicyHeader', +const phaseToBadgeMapping: Record = { + hot: { + color: euiThemeVars.euiColorVis9, + label: 'Hot', + }, + warm: { + color: euiThemeVars.euiColorVis5, + label: 'Warm', + }, + cold: { + color: euiThemeVars.euiColorVis1, + label: 'Cold', + }, + frozen: { + color: euiThemeVars.euiColorVis4, + label: 'Frozen', + }, + delete: { + color: 'default', + label: 'Delete', + }, +}; + +interface Props { + index: Index; + getUrlForApp: ApplicationStart['getUrlForApp']; +} + +export const IndexLifecycleSummary: FunctionComponent = ({ index, getUrlForApp }) => { + const { ilm: ilmData } = index; + // only ILM managed indices render the ILM tab + const ilm = ilmData as IlmExplainLifecycleLifecycleExplainManaged; + + // if ilm.phase is an unexpected value, then display a default badge + const phaseBadgeConfig = phaseToBadgeMapping[ilm.phase as Phase] ?? { + color: 'default', + label: ilm.phase, + }; + const lifecycleProperties = [ + { + title: i18n.translate( + 'xpack.indexLifecycleMgmt.indexLifecycleMgmtSummary.headers.policyNameTitle', { - defaultMessage: 'Lifecycle policy', + defaultMessage: 'Policy name', } ), - ], - [ - 'phase', - i18n.translate( - 'xpack.indexLifecycleMgmt.indexLifecycleMgmtSummary.headers.currentPhaseHeader', + description: ilm.policy, + }, + { + title: i18n.translate( + 'xpack.indexLifecycleMgmt.indexLifecycleMgmtSummary.headers.currentPhaseTitle', { defaultMessage: 'Current phase', } ), - ], - [ - 'action', - i18n.translate( - 'xpack.indexLifecycleMgmt.indexLifecycleMgmtSummary.headers.currentActionHeader', + description: {phaseBadgeConfig.label}, + }, + ]; + if (ilm.action) { + lifecycleProperties.push({ + title: i18n.translate( + 'xpack.indexLifecycleMgmt.indexLifecycleMgmtSummary.headers.currentActionTitle', { defaultMessage: 'Current action', } ), - ], - [ - 'action_time_millis', - i18n.translate( - 'xpack.indexLifecycleMgmt.indexLifecycleMgmtSummary.headers.currentActionTimeHeader', + description: {ilm.action}, + }); + } + if (ilm.action_time_millis) { + lifecycleProperties.push({ + title: i18n.translate( + 'xpack.indexLifecycleMgmt.indexLifecycleMgmtSummary.headers.currentActionTimeTitle', { defaultMessage: 'Current action time', } ), - ], - [ - 'failed_step', - i18n.translate( - 'xpack.indexLifecycleMgmt.indexLifecycleMgmtSummary.headers.failedStepHeader', + description: moment(ilm.action_time_millis).format('YYYY-MM-DD HH:mm:ss'), + }); + } + if (ilm.step) { + lifecycleProperties.push({ + title: i18n.translate( + 'xpack.indexLifecycleMgmt.indexLifecycleMgmtSummary.headers.currentStepTitle', { - defaultMessage: 'Failed step', + defaultMessage: 'Current step', } ), - ], - ]; -}; - -interface Props { - index: Index; - getUrlForApp: ApplicationStart['getUrlForApp']; -} - -export const IndexLifecycleSummary: FunctionComponent = ({ index, getUrlForApp }) => { - const [showPhaseExecutionPopover, setShowPhaseExecutionPopover] = useState(false); - const { ilm: ilmData } = index; - // only ILM managed indices render the ILM tab - const ilm = ilmData as IlmExplainLifecycleLifecycleExplainManaged; - - const togglePhaseExecutionPopover = () => { - setShowPhaseExecutionPopover(!showPhaseExecutionPopover); - }; - const closePhaseExecutionPopover = () => { - setShowPhaseExecutionPopover(false); - }; - const renderPhaseExecutionPopoverButton = () => { - const button = ( - - - - ); - return ( - - - - - - - - - - - - - {JSON.stringify(ilm.phase_execution, null, 2)} - - - - - ); - }; - const buildRows = () => { - const headers = getHeaders(); - const rows: { - left: JSX.Element[]; - right: JSX.Element[]; - } = { - left: [], - right: [], - }; - headers.forEach(([fieldName, label], arrayIndex) => { - const value = ilm[fieldName]; - let content; - if (fieldName === 'action_time_millis') { - content = moment(value as string).format('YYYY-MM-DD HH:mm:ss'); - } else if (fieldName === 'policy') { - content = ( - - {value} - - ); - } else { - content = value; - } - content = content || '-'; - const cell = ( - - - {label} - - - {content} - - - ); - if (arrayIndex % 2 === 0) { - rows.left.push(cell); - } else { - rows.right.push(cell); - } + description: {ilm.step}, }); - if (ilm.phase_execution) { - rows.right.push(renderPhaseExecutionPopoverButton()); - } - return rows; - }; - - const { left, right } = buildRows(); + } return ( <> - -

    - -

    -
    - {ilm.step_info && ilm.step_info.type ? ( - <> - - - } - iconType="cross" - > - {ilm.step_info.type}: {ilm.step_info.reason} - - - ) : null} - {ilm.step_info && ilm.step_info!.message ? ( - <> - - - } - > - {ilm.step_info!.message} - - - ) : null} - - - - {left} + + + + + + +

    + +

    +
    +
    + + + + + +
    + + + +
    - - {right} + + {ilm.step_info && ilm.step === 'ERROR' && ( + // there is an error + <> + + +

    + +

    + + + {JSON.stringify( + { failed_step: ilm.failed_step, step_info: ilm.step_info }, + null, + 2 + )} + +
    +
    + + + )} + {ilm.step_info && ilm.step !== 'ERROR' && ( + // ILM is waiting for the step to complete + <> + + +

    + +

    + + + {JSON.stringify(ilm.step_info, null, 2)} + +
    +
    + + + )} + {ilm.phase_execution && ( + + +

    + +

    +
    + + + {JSON.stringify(ilm.phase_execution, null, 2)} + +
    + )}
    diff --git a/x-pack/plugins/index_lifecycle_management/server/index.ts b/x-pack/plugins/index_lifecycle_management/server/index.ts index 2f4c3a4706534..b4789a4868eba 100644 --- a/x-pack/plugins/index_lifecycle_management/server/index.ts +++ b/x-pack/plugins/index_lifecycle_management/server/index.ts @@ -6,9 +6,10 @@ */ import { PluginInitializerContext } from '@kbn/core/server'; -import { IndexLifecycleManagementServerPlugin } from './plugin'; export { config } from './config'; -export const plugin = (ctx: PluginInitializerContext) => - new IndexLifecycleManagementServerPlugin(ctx); +export const plugin = async (ctx: PluginInitializerContext) => { + const { IndexLifecycleManagementServerPlugin } = await import('./plugin'); + return new IndexLifecycleManagementServerPlugin(ctx); +}; diff --git a/x-pack/plugins/index_lifecycle_management/tsconfig.json b/x-pack/plugins/index_lifecycle_management/tsconfig.json index e69bfeb2cc92d..6632d318e5d9f 100644 --- a/x-pack/plugins/index_lifecycle_management/tsconfig.json +++ b/x-pack/plugins/index_lifecycle_management/tsconfig.json @@ -35,6 +35,7 @@ "@kbn/core-http-browser", "@kbn/config-schema", "@kbn/shared-ux-router", + "@kbn/ui-theme", "@kbn/shared-ux-link-redirect-app" ], "exclude": [ diff --git a/x-pack/plugins/index_management/__jest__/client_integration/home/enrich_policies.test.tsx b/x-pack/plugins/index_management/__jest__/client_integration/home/enrich_policies.test.tsx index 6d0cafe0c938b..e3666d19f88b0 100644 --- a/x-pack/plugins/index_management/__jest__/client_integration/home/enrich_policies.test.tsx +++ b/x-pack/plugins/index_management/__jest__/client_integration/home/enrich_policies.test.tsx @@ -31,8 +31,7 @@ jest.mock('@kbn/kibana-react-plugin/public', () => { }; }); -// Failing: See https://github.com/elastic/kibana/issues/170239 -describe.skip('Enrich policies tab', () => { +describe('Enrich policies tab', () => { const { httpSetup, httpRequestsMockHelpers, setDelayResponse } = setupEnvironment(); let testBed: EnrichPoliciesTestBed; @@ -141,7 +140,7 @@ describe.skip('Enrich policies tab', () => { // Should have made a call to load the policies after the reload // button is clicked. - expect(httpSetup.get.mock.calls).toHaveLength(1); + expect(httpSetup.get.mock.calls.length).toBeGreaterThan(0); }); describe('details flyout', () => { diff --git a/x-pack/plugins/index_management/public/application/services/routing.ts b/x-pack/plugins/index_management/public/application/services/routing.ts index 3ec13eca06516..02e1410e9551c 100644 --- a/x-pack/plugins/index_management/public/application/services/routing.ts +++ b/x-pack/plugins/index_management/public/application/services/routing.ts @@ -34,10 +34,6 @@ export const getTemplateCloneLink = (name: string, isLegacy?: boolean) => { return encodeURI(url); }; -export const getILMPolicyPath = (policyName: string) => { - return `/data/index_lifecycle_management/policies/edit/${encodeURIComponent(policyName)}`; -}; - export const getIndexListUri = (filter?: string, includeHiddenIndices?: boolean) => { const hiddenIndicesParam = typeof includeHiddenIndices !== 'undefined' ? includeHiddenIndices : false; diff --git a/x-pack/plugins/index_management/server/index.ts b/x-pack/plugins/index_management/server/index.ts index ab6b0741274ff..127599066ab66 100644 --- a/x-pack/plugins/index_management/server/index.ts +++ b/x-pack/plugins/index_management/server/index.ts @@ -7,11 +7,12 @@ import { PluginInitializerContext } from '@kbn/core/server'; -import { IndexMgmtServerPlugin } from './plugin'; - export { config } from './config'; -export const plugin = (context: PluginInitializerContext) => new IndexMgmtServerPlugin(context); +export const plugin = async (context: PluginInitializerContext) => { + const { IndexMgmtServerPlugin } = await import('./plugin'); + return new IndexMgmtServerPlugin(context); +}; /** @public */ export type { Dependencies } from './types'; diff --git a/x-pack/plugins/index_management/server/lib/enrich_policies.ts b/x-pack/plugins/index_management/server/lib/enrich_policies.ts index f31cda9e5f963..db25603817e64 100644 --- a/x-pack/plugins/index_management/server/lib/enrich_policies.ts +++ b/x-pack/plugins/index_management/server/lib/enrich_policies.ts @@ -45,7 +45,12 @@ const create = ( }; const execute = (client: IScopedClusterClient, policyName: string) => { - return client.asCurrentUser.enrich.executePolicy({ name: policyName }); + // Enrich policy executions can last as short as a few seconds to as long as half and hour or longer. + // In order to prevent the enrich policies UI from timing out, we are disabling `waitForCompletion`. + return client.asCurrentUser.enrich.executePolicy({ + name: policyName, + wait_for_completion: false, + }); }; const remove = (client: IScopedClusterClient, policyName: string) => { diff --git a/x-pack/plugins/infra/server/index.ts b/x-pack/plugins/infra/server/index.ts index 2bfd868831ecc..96ac6dc162c24 100644 --- a/x-pack/plugins/infra/server/index.ts +++ b/x-pack/plugins/infra/server/index.ts @@ -6,12 +6,13 @@ */ import { PluginInitializerContext } from '@kbn/core/server'; -import { config, InfraConfig, InfraServerPlugin } from './plugin'; +import { config, InfraConfig } from './plugin'; export type { InfraPluginSetup, InfraPluginStart, InfraRequestHandlerContext } from './types'; export type { InfraConfig }; export { config }; -export function plugin(context: PluginInitializerContext) { +export async function plugin(context: PluginInitializerContext) { + const { InfraServerPlugin } = await import('./plugin'); return new InfraServerPlugin(context); } diff --git a/x-pack/plugins/ingest_pipelines/server/index.ts b/x-pack/plugins/ingest_pipelines/server/index.ts index d120f60ef8a2d..aac84c37591db 100644 --- a/x-pack/plugins/ingest_pipelines/server/index.ts +++ b/x-pack/plugins/ingest_pipelines/server/index.ts @@ -5,8 +5,7 @@ * 2.0. */ -import { IngestPipelinesPlugin } from './plugin'; - -export function plugin() { +export async function plugin() { + const { IngestPipelinesPlugin } = await import('./plugin'); return new IngestPipelinesPlugin(); } diff --git a/x-pack/plugins/kubernetes_security/server/index.ts b/x-pack/plugins/kubernetes_security/server/index.ts index 7ff5edf027a09..b51098c136ad0 100644 --- a/x-pack/plugins/kubernetes_security/server/index.ts +++ b/x-pack/plugins/kubernetes_security/server/index.ts @@ -6,8 +6,8 @@ */ import { PluginInitializerContext } from '@kbn/core/server'; -import { KubernetesSecurityPlugin } from './plugin'; -export function plugin(initializerContext: PluginInitializerContext) { +export async function plugin(initializerContext: PluginInitializerContext) { + const { KubernetesSecurityPlugin } = await import('./plugin'); return new KubernetesSecurityPlugin(initializerContext); } diff --git a/x-pack/plugins/lens/public/app_plugin/save_modal.tsx b/x-pack/plugins/lens/public/app_plugin/save_modal.tsx index 1a4d7c5bfb028..508e8409eb269 100644 --- a/x-pack/plugins/lens/public/app_plugin/save_modal.tsx +++ b/x-pack/plugins/lens/public/app_plugin/save_modal.tsx @@ -24,6 +24,7 @@ export interface Props { savingToLibraryPermitted?: boolean; originatingApp?: string; + getOriginatingPath?: (dashboardId: string) => string; allowByValueEmbeddables: boolean; savedObjectsTagging?: SavedObjectTaggingPluginStart; @@ -35,7 +36,7 @@ export interface Props { getAppNameFromId: () => string | undefined; returnToOriginSwitchLabel?: string; - + returnToOrigin?: boolean; onClose: () => void; onSave: (props: SaveProps, options: { saveToLibrary: boolean }) => void; } @@ -43,6 +44,7 @@ export interface Props { export const SaveModal = (props: Props) => { const { originatingApp, + getOriginatingPath, savingToLibraryPermitted, savedObjectsTagging, tagsIds, @@ -54,10 +56,11 @@ export const SaveModal = (props: Props) => { getAppNameFromId, onClose, onSave, + returnToOrigin, } = props; // Use the modal with return-to-origin features if we're in an app's edit flow or if by-value embeddables are disabled - if (originatingApp || !allowByValueEmbeddables) { + if ((originatingApp || !allowByValueEmbeddables) && returnToOrigin !== false) { return ( { defaultMessage: 'Lens visualization', })} data-test-subj="lnsApp_saveModalDashboard" + getOriginatingPath={getOriginatingPath} /> ); }; diff --git a/x-pack/plugins/lens/public/app_plugin/save_modal_container.tsx b/x-pack/plugins/lens/public/app_plugin/save_modal_container.tsx index 9a9fb2661f308..e01f68d9e4b30 100644 --- a/x-pack/plugins/lens/public/app_plugin/save_modal_container.tsx +++ b/x-pack/plugins/lens/public/app_plugin/save_modal_container.tsx @@ -25,11 +25,12 @@ type ExtraProps = Pick & export type SaveModalContainerProps = { originatingApp?: string; + getOriginatingPath?: (dashboardId: string) => string; persistedDoc?: Document; lastKnownDoc?: Document; returnToOriginSwitchLabel?: string; onClose: () => void; - onSave?: () => void; + onSave?: (saveProps: SaveProps) => void; runSave?: (saveProps: SaveProps, options: { saveToLibrary: boolean }) => void; isSaveable?: boolean; getAppNameFromId?: () => string | undefined; @@ -44,6 +45,7 @@ export function SaveModalContainer({ runSave, persistedDoc, originatingApp, + getOriginatingPath, initialInput, redirectTo, redirectToOrigin, @@ -119,6 +121,7 @@ export function SaveModalContainer({ redirectTo, redirectToOrigin, originatingApp, + getOriginatingPath, getIsByValueMode: () => false, onAppLeave: () => {}, savedObjectStore: lensServices.savedObjectStore, @@ -126,7 +129,7 @@ export function SaveModalContainer({ saveProps, options ).then(() => { - onSave?.(); + onSave?.(saveProps); onClose(); }); } @@ -137,6 +140,7 @@ export function SaveModalContainer({ return ( ); } @@ -158,11 +163,15 @@ const redirectToDashboard = ({ embeddableInput, dashboardFeatureFlag, dashboardId, + originatingApp, + getOriginatingPath, stateTransfer, }: { embeddableInput: LensEmbeddableInput; dashboardId: string; dashboardFeatureFlag: LensAppServices['dashboardFeatureFlag']; + originatingApp?: string; + getOriginatingPath?: (dashboardId: string) => string | undefined; stateTransfer: LensAppServices['stateTransfer']; }) => { if (!dashboardFeatureFlag.allowByValueEmbeddables) { @@ -174,8 +183,11 @@ const redirectToDashboard = ({ type: LENS_EMBEDDABLE_TYPE, }; - const path = dashboardId === 'new' ? '#/create' : `#/view/${dashboardId}`; - stateTransfer.navigateToWithEmbeddablePackage('dashboards', { + const path = + getOriginatingPath?.(dashboardId) ?? + (dashboardId === 'new' ? '#/create' : `#/view/${dashboardId}`); + const appId = originatingApp ?? 'dashboards'; + stateTransfer.navigateToWithEmbeddablePackage(appId, { state, path, }); @@ -208,6 +220,7 @@ export const runSaveLensVisualization = async ( getIsByValueMode: () => boolean; persistedDoc?: Document; originatingApp?: string; + getOriginatingPath?: (dashboardId: string) => string; textBasedLanguageSave?: boolean; switchDatasource?: () => void; savedObjectStore: SavedObjectIndexStore; @@ -248,7 +261,6 @@ export const runSaveLensVisualization = async ( persistedDoc && savedObjectsTagging ? savedObjectsTagging.ui.getTagIdsFromReferences(persistedDoc.references) : []; - references = savedObjectsTagging.ui.updateTagsReferences( references, saveProps.newTags || tagsIds @@ -305,7 +317,6 @@ export const runSaveLensVisualization = async ( timeRange: saveProps.panelTimeRange, }; } - if (saveProps.returnToOrigin && redirectToOrigin) { // disabling the validation on app leave because the document has been saved. onAppLeave?.((actions) => { @@ -323,6 +334,8 @@ export const runSaveLensVisualization = async ( dashboardId: saveProps.dashboardId, stateTransfer, dashboardFeatureFlag, + originatingApp: props.originatingApp, + getOriginatingPath: props.getOriginatingPath, }); return; } diff --git a/x-pack/plugins/lens/public/app_plugin/tags_saved_object_save_modal_dashboard_wrapper.tsx b/x-pack/plugins/lens/public/app_plugin/tags_saved_object_save_modal_dashboard_wrapper.tsx index 39c2f55bdd676..9f932d0b23fd8 100644 --- a/x-pack/plugins/lens/public/app_plugin/tags_saved_object_save_modal_dashboard_wrapper.tsx +++ b/x-pack/plugins/lens/public/app_plugin/tags_saved_object_save_modal_dashboard_wrapper.tsx @@ -28,6 +28,7 @@ export type TagEnhancedSavedObjectSaveModalDashboardProps = Omit< initialTags: string[]; savedObjectsTagging?: SavedObjectTaggingPluginStart; onSave: (props: DashboardSaveProps) => void; + getOriginatingPath?: (dashboardId: string) => string; }; const SavedObjectSaveModalDashboard = withSuspense(LazySavedObjectSaveModalDashboard); diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/chart_switch.tsx b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/chart_switch.tsx index a88cd0619f001..c40c81285dc15 100644 --- a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/chart_switch.tsx +++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/chart_switch.tsx @@ -20,7 +20,7 @@ import { } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n-react'; -import { ToolbarButton } from '@kbn/kibana-react-plugin/public'; +import { ToolbarButton } from '@kbn/shared-ux-button-toolbar'; import { Visualization, FramePublicAPI, @@ -429,12 +429,13 @@ export const ChartSwitch = memo(function ChartSwitch(props: Props) { onClick={() => setFlyoutOpen(!flyoutOpen)} data-test-subj="lnsChartSwitchPopover" fontWeight="bold" - > - - + label={ + + } + /> } isOpen={flyoutOpen} closePopover={() => setFlyoutOpen(false)} diff --git a/x-pack/plugins/lens/public/plugin.ts b/x-pack/plugins/lens/public/plugin.ts index 63eab92016d50..460864d1c86f2 100644 --- a/x-pack/plugins/lens/public/plugin.ts +++ b/x-pack/plugins/lens/public/plugin.ts @@ -127,6 +127,8 @@ import { downloadCsvShareProvider } from './app_plugin/csv_download_provider/csv import { CONTENT_ID, LATEST_VERSION } from '../common/content_management'; import type { EditLensConfigurationProps } from './app_plugin/shared/edit_on_the_fly/get_edit_lens_configuration'; +export type { SaveProps } from './app_plugin'; + export interface LensPluginSetupDependencies { urlForwarding: UrlForwardingSetup; expressions: ExpressionsSetup; diff --git a/x-pack/plugins/lens/public/shared_components/dataview_picker/trigger.tsx b/x-pack/plugins/lens/public/shared_components/dataview_picker/trigger.tsx index 0669b7b08f07e..f0a4648a3606e 100644 --- a/x-pack/plugins/lens/public/shared_components/dataview_picker/trigger.tsx +++ b/x-pack/plugins/lens/public/shared_components/dataview_picker/trigger.tsx @@ -101,7 +101,7 @@ export function TriggerButton({ fullWidth {...colorProp} {...rest} - textProps={{ style: { width: '100%', lineHeight: '100%' } }} + textProps={{ style: { width: '100%', lineHeight: '1.2em' } }} > 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 34cdcfe2e18b1..64a374bae7052 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,10 +15,9 @@ import { EuiFieldNumber, } from '@elastic/eui'; import { Position, VerticalAlignment, HorizontalAlignment } from '@elastic/charts'; -import { ToolbarButtonProps } from '@kbn/kibana-react-plugin/public'; import { LegendSize } from '@kbn/visualizations-plugin/public'; import { useDebouncedValue } from '@kbn/visualization-ui-components'; -import { ToolbarPopover } from '../toolbar_popover'; +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'; @@ -119,7 +118,7 @@ export interface LegendSettingsPopoverProps { /** * Button group position */ - groupPosition?: ToolbarButtonProps['groupPosition']; + groupPosition?: ToolbarPopoverProps['groupPosition']; /** * Legend size in pixels */ diff --git a/x-pack/plugins/lens/public/shared_components/toolbar_popover.tsx b/x-pack/plugins/lens/public/shared_components/toolbar_popover.tsx index dbb3d69588624..c8e096cbbb8a7 100644 --- a/x-pack/plugins/lens/public/shared_components/toolbar_popover.tsx +++ b/x-pack/plugins/lens/public/shared_components/toolbar_popover.tsx @@ -7,8 +7,8 @@ import './toolbar_popover.scss'; import React, { useState } from 'react'; -import { EuiFlexItem, EuiPopover, EuiIcon, EuiPopoverTitle, IconType } from '@elastic/eui'; -import { ToolbarButton, ToolbarButtonProps } from '@kbn/kibana-react-plugin/public'; +import { EuiFlexItem, EuiPopover, EuiPopoverTitle, IconType } from '@elastic/eui'; +import { ToolbarButton, ToolbarButtonProps } from '@kbn/shared-ux-button-toolbar'; import { EuiIconLegend } from '@kbn/chart-icons'; const typeToIconMap: { [type: string]: string | IconType } = { @@ -35,7 +35,7 @@ export interface ToolbarPopoverProps { /** * Button group position */ - groupPosition?: ToolbarButtonProps['groupPosition']; + groupPosition?: ToolbarButtonProps<'iconButton'>['groupPosition']; buttonDataTestSubj?: string; panelClassName?: string; handleClose?: () => void; @@ -63,18 +63,16 @@ export const ToolbarPopover: React.FunctionComponent = ({ aria-label={title} button={ { setOpen(!open); }} - title={title} - hasArrow={false} + aria-label={title} isDisabled={isDisabled} groupPosition={groupPosition} - dataTestSubj={buttonDataTestSubj} - > - - + data-test-subj={buttonDataTestSubj} + /> } isOpen={open} closePopover={() => { 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 11077414e25b8..6b56d4f82ca19 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 @@ -10,7 +10,7 @@ import { EuiSwitch, IconType, EuiFormRow, EuiButtonGroup, EuiSelect } from '@ela import { i18n } from '@kbn/i18n'; import { isEqual } from 'lodash'; import { AxisExtentConfig, YScaleType } from '@kbn/expression-xy-plugin/common'; -import { ToolbarButtonProps } from '@kbn/kibana-react-plugin/public'; +import { ToolbarButtonProps } from '@kbn/shared-ux-button-toolbar'; import { EuiIconAxisBottom, EuiIconAxisLeft, @@ -131,7 +131,7 @@ const popoverConfig = ( isHorizontal: boolean ): { icon: IconType; - groupPosition: ToolbarButtonProps['groupPosition']; + groupPosition: ToolbarButtonProps<'iconButton'>['groupPosition']; popoverTitle: string; buttonDataTestSubj: string; } => { diff --git a/x-pack/plugins/lens/public/visualizations/xy/xy_config_panel/layer_header.tsx b/x-pack/plugins/lens/public/visualizations/xy/xy_config_panel/layer_header.tsx index 941b6d01e6b40..99c7b2bec30d4 100644 --- a/x-pack/plugins/lens/public/visualizations/xy/xy_config_panel/layer_header.tsx +++ b/x-pack/plugins/lens/public/visualizations/xy/xy_config_panel/layer_header.tsx @@ -15,8 +15,10 @@ import { EuiPopoverTitle, useEuiTheme, EuiIconTip, + EuiFlexGroup, + EuiFlexItem, } from '@elastic/eui'; -import { ToolbarButton } from '@kbn/kibana-react-plugin/public'; +import { ToolbarButton } from '@kbn/shared-ux-button-toolbar'; import { IconChartBarReferenceLine, IconChartBarAnnotations } from '@kbn/chart-icons'; import { euiThemeVars } from '@kbn/ui-theme'; import { css } from '@emotion/react'; @@ -231,18 +233,22 @@ const DataLayerHeaderTrigger = function ({ return ( - <> - - - {currentVisType.fullLabel || currentVisType.label} - - - + label={ + + + + + + + {currentVisType.fullLabel || currentVisType.label} + + + + } + /> ); }; diff --git a/x-pack/plugins/lens/server/index.ts b/x-pack/plugins/lens/server/index.ts index 6b9f823c3bbc6..80a61445b9cdb 100644 --- a/x-pack/plugins/lens/server/index.ts +++ b/x-pack/plugins/lens/server/index.ts @@ -6,9 +6,11 @@ */ import type { PluginInitializerContext } from '@kbn/core-plugins-server'; -import { LensServerPlugin } from './plugin'; export type { LensServerPluginSetup } from './plugin'; -export const plugin = (initContext: PluginInitializerContext) => new LensServerPlugin(initContext); +export const plugin = async (initContext: PluginInitializerContext) => { + const { LensServerPlugin } = await import('./plugin'); + return new LensServerPlugin(initContext); +}; export type { LensDocShape715 } from './migrations/types'; diff --git a/x-pack/plugins/lens/tsconfig.json b/x-pack/plugins/lens/tsconfig.json index d342ddf99fc77..12f737244bcb0 100644 --- a/x-pack/plugins/lens/tsconfig.json +++ b/x-pack/plugins/lens/tsconfig.json @@ -90,7 +90,8 @@ "@kbn/search-response-warnings", "@kbn/logging", "@kbn/core-plugins-server", - "@kbn/field-utils" + "@kbn/field-utils", + "@kbn/shared-ux-button-toolbar" ], "exclude": [ "target/**/*", diff --git a/x-pack/plugins/license_management/server/index.ts b/x-pack/plugins/license_management/server/index.ts index 1a8eba1e2610e..55bd9e0f67fcf 100644 --- a/x-pack/plugins/license_management/server/index.ts +++ b/x-pack/plugins/license_management/server/index.ts @@ -7,8 +7,9 @@ import { PluginInitializerContext } from '@kbn/core/server'; -import { LicenseManagementServerPlugin } from './plugin'; - export { config } from './config'; -export const plugin = (ctx: PluginInitializerContext) => new LicenseManagementServerPlugin(); +export const plugin = async (ctx: PluginInitializerContext) => { + const { LicenseManagementServerPlugin } = await import('./plugin'); + return new LicenseManagementServerPlugin(); +}; diff --git a/x-pack/plugins/licensing/server/index.ts b/x-pack/plugins/licensing/server/index.ts index 4cfa04089d8c5..af95086815221 100644 --- a/x-pack/plugins/licensing/server/index.ts +++ b/x-pack/plugins/licensing/server/index.ts @@ -6,9 +6,11 @@ */ import { PluginInitializerContext } from '@kbn/core/server'; -import { LicensingPlugin } from './plugin'; -export const plugin = (context: PluginInitializerContext) => new LicensingPlugin(context); +export const plugin = async (context: PluginInitializerContext) => { + const { LicensingPlugin } = await import('./plugin'); + return new LicensingPlugin(context); +}; export type { LicenseCheckState, diff --git a/x-pack/plugins/lists/server/index.ts b/x-pack/plugins/lists/server/index.ts index ef63343d8f5ea..f4d6805057c41 100644 --- a/x-pack/plugins/lists/server/index.ts +++ b/x-pack/plugins/lists/server/index.ts @@ -8,9 +8,9 @@ import { PluginConfigDescriptor, PluginInitializerContext } from '@kbn/core/server'; import { ConfigSchema } from './config'; -import { ListPlugin } from './plugin'; +import type { ListPlugin } from './plugin'; -// exporting these since its required at top level in siem plugin +// exporting these since it's required at top level in siem plugin export { ListClient } from './services/lists/list_client'; export type { CreateExceptionListItemOptions, @@ -40,5 +40,7 @@ export const config: PluginConfigDescriptor = { export { ErrorWithStatusCode as ListsErrorWithStatusCode } from './error_with_status_code'; -export const plugin = (initializerContext: PluginInitializerContext): ListPlugin => - new ListPlugin(initializerContext); +export const plugin = async (initializerContext: PluginInitializerContext): Promise => { + const { ListPlugin } = await import('./plugin'); + return new ListPlugin(initializerContext); +}; diff --git a/x-pack/plugins/log_explorer/server/index.ts b/x-pack/plugins/log_explorer/server/index.ts index 634e4cfe02566..38aab9b85065b 100644 --- a/x-pack/plugins/log_explorer/server/index.ts +++ b/x-pack/plugins/log_explorer/server/index.ts @@ -5,6 +5,7 @@ * 2.0. */ -import { LogExplorerServerPlugin } from './plugin'; - -export const plugin = () => new LogExplorerServerPlugin(); +export const plugin = async () => { + const { LogExplorerServerPlugin } = await import('./plugin'); + return new LogExplorerServerPlugin(); +}; diff --git a/x-pack/plugins/logs_shared/server/index.ts b/x-pack/plugins/logs_shared/server/index.ts index 1a894ddb52abd..efc7da6a9d326 100644 --- a/x-pack/plugins/logs_shared/server/index.ts +++ b/x-pack/plugins/logs_shared/server/index.ts @@ -6,7 +6,6 @@ */ import { PluginInitializerContext } from '@kbn/core/server'; -import { LogsSharedPlugin } from './plugin'; export type { LogsSharedPluginSetup, LogsSharedPluginStart } from './types'; export type { @@ -17,6 +16,7 @@ export type { export { config } from './config'; export { logViewSavedObjectName } from './saved_objects'; -export function plugin(context: PluginInitializerContext) { +export async function plugin(context: PluginInitializerContext) { + const { LogsSharedPlugin } = await import('./plugin'); return new LogsSharedPlugin(context); } diff --git a/x-pack/plugins/logs_shared/server/services/log_views/log_views_client.test.ts b/x-pack/plugins/logs_shared/server/services/log_views/log_views_client.test.ts index 125167d6deea8..e50d08c630eb7 100644 --- a/x-pack/plugins/logs_shared/server/services/log_views/log_views_client.test.ts +++ b/x-pack/plugins/logs_shared/server/services/log_views/log_views_client.test.ts @@ -249,6 +249,7 @@ describe('LogViewsClient class', () => { }, ], "dataViewReference": DataView { + "allowHidden": false, "allowNoIndex": false, "deleteFieldFormat": [Function], "deleteScriptedFieldInternal": [Function], @@ -274,6 +275,7 @@ describe('LogViewsClient class', () => { }, "fields": FldList [], "flattenHit": [Function], + "getAllowHidden": [Function], "getFieldAttrs": [Function], "getIndexPattern": [Function], "getName": [Function], @@ -298,6 +300,7 @@ describe('LogViewsClient class', () => { }, }, "scriptedFields": Array [], + "setAllowHidden": [Function], "setFieldFormat": [Function], "setIndexPattern": [Function], "shortDotsEnable": false, diff --git a/x-pack/plugins/logstash/server/index.ts b/x-pack/plugins/logstash/server/index.ts index 3e89eeb9b5795..530ff1b7d5452 100644 --- a/x-pack/plugins/logstash/server/index.ts +++ b/x-pack/plugins/logstash/server/index.ts @@ -6,6 +6,8 @@ */ import { PluginInitializerContext } from '@kbn/core/server'; -import { LogstashPlugin } from './plugin'; -export const plugin = (context: PluginInitializerContext) => new LogstashPlugin(context); +export const plugin = async (context: PluginInitializerContext) => { + const { LogstashPlugin } = await import('./plugin'); + return new LogstashPlugin(context); +}; diff --git a/x-pack/plugins/maps/common/descriptor_types/data_request_descriptor_types.ts b/x-pack/plugins/maps/common/descriptor_types/data_request_descriptor_types.ts index 6dd28fd0e3683..1977173a0207c 100644 --- a/x-pack/plugins/maps/common/descriptor_types/data_request_descriptor_types.ts +++ b/x-pack/plugins/maps/common/descriptor_types/data_request_descriptor_types.ts @@ -11,6 +11,7 @@ import type { KibanaExecutionContext } from '@kbn/core/public'; import type { Query } from '@kbn/data-plugin/common'; import type { Filter } from '@kbn/es-query'; import type { TimeRange } from '@kbn/es-query'; +import type { SearchResponseWarning } from '@kbn/search-response-warnings'; import { MapExtent } from './map_descriptor'; export type Timeslice = { @@ -91,6 +92,7 @@ export type VectorTileLayerMeta = { export type DataRequestMeta = { // request stop time in milliseconds since epoch requestStopTime?: number; + warnings?: SearchResponseWarning[]; } & Partial< SourceRequestMeta & VectorSourceRequestMeta & @@ -123,5 +125,5 @@ export type DataRequestDescriptor = { dataRequestToken?: symbol; data?: object; dataRequestMeta?: DataRequestMeta; - error?: string; + error?: Error; }; diff --git a/x-pack/plugins/maps/common/mvt_request_body.test.ts b/x-pack/plugins/maps/common/mvt_request_body.test.ts index bb8945231b701..3a8c654b2979d 100644 --- a/x-pack/plugins/maps/common/mvt_request_body.test.ts +++ b/x-pack/plugins/maps/common/mvt_request_body.test.ts @@ -52,6 +52,26 @@ describe('getHitsTileRequest', () => { expect(path).toEqual('/my%20index/_mvt/my%20location/0/0/0'); }); + test(`Should use requestBody.size to set both track_total_hits and size parameters`, () => { + const searchRequest = { + size: 20000, + runtime_mappings: {}, + query: {}, + }; + const { body } = getHitsTileRequest({ + buffer: 5, + risonRequestBody: rison.encode(searchRequest), + geometryFieldName: 'my location', + hasLabels: true, + index: 'my index', + x: 0, + y: 0, + z: 0, + }); + expect(body?.track_total_hits).toEqual(20001); + expect(body?.size).toEqual(20000); + }); + describe('sort', () => { test(`Should include sort`, () => { const searchRequest = { diff --git a/x-pack/plugins/maps/common/mvt_request_body.ts b/x-pack/plugins/maps/common/mvt_request_body.ts index 9a765505960ef..d87707ad6b908 100644 --- a/x-pack/plugins/maps/common/mvt_request_body.ts +++ b/x-pack/plugins/maps/common/mvt_request_body.ts @@ -83,6 +83,7 @@ export function getHitsTileRequest({ if (!requestBody) { throw new Error('Required requestBody parameter not provided'); } + const size = typeof requestBody.size === 'number' ? requestBody.size : 10000; const tileRequestBody = { buffer, grid_precision: 0, // no aggs @@ -90,7 +91,12 @@ export function getHitsTileRequest({ extent: 4096, // full resolution, query: requestBody.query, runtime_mappings: requestBody.runtime_mappings, - track_total_hits: typeof requestBody.size === 'number' ? requestBody.size + 1 : false, + // Number of hits matching the query to count accurately + // Used to notify users of truncated results + track_total_hits: size + 1, + // Maximum number of features to return in the hits layer + // Used to fetch number of hits that correspondes with track_total_hits + size, with_labels: hasLabels, } as SearchMvtRequest['body']; if (requestBody.fields) { diff --git a/x-pack/plugins/maps/public/actions/data_request_actions.ts b/x-pack/plugins/maps/public/actions/data_request_actions.ts index 78803c3470227..c700859787cbe 100644 --- a/x-pack/plugins/maps/public/actions/data_request_actions.ts +++ b/x-pack/plugins/maps/public/actions/data_request_actions.ts @@ -62,7 +62,7 @@ export type DataRequestContext = { data: object, resultsMeta?: DataRequestMeta ): void; - onLoadError(dataId: string, requestToken: symbol, errorMessage: string): void; + onLoadError(dataId: string, requestToken: symbol, error: Error): void; setJoinError(joinIndex: number, errorMessage?: string): void; updateSourceData(newData: object): void; isRequestStillActive(dataId: string, requestToken: symbol): boolean; @@ -132,8 +132,8 @@ function getDataRequestContext( dispatch(startDataLoad(layerId, dataId, requestToken, meta)), stopLoading: (dataId: string, requestToken: symbol, data: object, meta: DataRequestMeta) => dispatch(endDataLoad(layerId, dataId, requestToken, data, meta)), - onLoadError: (dataId: string, requestToken: symbol, errorMessage: string) => - dispatch(onDataLoadError(layerId, dataId, requestToken, errorMessage)), + onLoadError: (dataId: string, requestToken: symbol, error: Error) => + dispatch(onDataLoadError(layerId, dataId, requestToken, error)), setJoinError: (joinIndex: number, errorMessage?: string) => { dispatch(setJoinError(layerId, joinIndex, errorMessage)); }, @@ -312,12 +312,7 @@ function endDataLoad( }; } -function onDataLoadError( - layerId: string, - dataId: string, - requestToken: symbol, - errorMessage: string -) { +function onDataLoadError(layerId: string, dataId: string, requestToken: symbol, error: Error) { return async ( dispatch: ThunkDispatch, getState: () => MapStoreState @@ -329,7 +324,7 @@ function onDataLoadError( eventHandlers.onDataLoadError({ layerId, dataId, - errorMessage, + errorMessage: error.message, }); } @@ -337,7 +332,7 @@ function onDataLoadError( type: LAYER_DATA_LOAD_ERROR, layerId, dataId, - errorMessage, + error, requestToken, }); }; diff --git a/x-pack/plugins/maps/public/classes/layers/__fixtures__/mock_sync_context.ts b/x-pack/plugins/maps/public/classes/layers/__fixtures__/mock_sync_context.ts index 9edbabe2905da..96fda4a4ec54f 100644 --- a/x-pack/plugins/maps/public/classes/layers/__fixtures__/mock_sync_context.ts +++ b/x-pack/plugins/maps/public/classes/layers/__fixtures__/mock_sync_context.ts @@ -13,7 +13,7 @@ import { DataRequestMeta, DataFilters } from '../../../../common/descriptor_type export class MockSyncContext implements DataRequestContext { dataFilters: DataFilters; isRequestStillActive: (dataId: string, requestToken: symbol) => boolean; - onLoadError: (dataId: string, requestToken: symbol, errorMessage: string) => void; + onLoadError: (dataId: string, requestToken: symbol, error: Error) => void; registerCancelCallback: (requestToken: symbol, callback: () => void) => void; startLoading: (dataId: string, requestToken: symbol, meta: DataRequestMeta) => void; stopLoading: (dataId: string, requestToken: symbol, data: object, meta: DataRequestMeta) => void; diff --git a/x-pack/plugins/maps/public/classes/layers/ems_vector_tile_layer/ems_vector_tile_layer.test.ts b/x-pack/plugins/maps/public/classes/layers/ems_vector_tile_layer/ems_vector_tile_layer.test.ts index 557fac4c25bf3..f5de54be72375 100644 --- a/x-pack/plugins/maps/public/classes/layers/ems_vector_tile_layer/ems_vector_tile_layer.test.ts +++ b/x-pack/plugins/maps/public/classes/layers/ems_vector_tile_layer/ems_vector_tile_layer.test.ts @@ -43,8 +43,8 @@ describe('EmsVectorTileLayer', () => { startLoading: (requestId: string, token: string, meta: unknown) => { actualMeta = meta; }, - onLoadError: (requestId: string, token: string, message: string) => { - actualErrorMessage = message; + onLoadError: (requestId: string, token: string, error: Error) => { + actualErrorMessage = error.message; }, dataFilters: { foo: 'bar' } as unknown as DataFilters, } as unknown as DataRequestContext; diff --git a/x-pack/plugins/maps/public/classes/layers/ems_vector_tile_layer/ems_vector_tile_layer.tsx b/x-pack/plugins/maps/public/classes/layers/ems_vector_tile_layer/ems_vector_tile_layer.tsx index dac4d628570f0..78f0297a0f38d 100644 --- a/x-pack/plugins/maps/public/classes/layers/ems_vector_tile_layer/ems_vector_tile_layer.tsx +++ b/x-pack/plugins/maps/public/classes/layers/ems_vector_tile_layer/ems_vector_tile_layer.tsx @@ -137,7 +137,7 @@ export class EmsVectorTileLayer extends AbstractLayer { }; stopLoading(SOURCE_DATA_REQUEST_ID, requestToken, data); } catch (error) { - onLoadError(SOURCE_DATA_REQUEST_ID, requestToken, error.message); + onLoadError(SOURCE_DATA_REQUEST_ID, requestToken, error); } } diff --git a/x-pack/plugins/maps/public/classes/layers/layer.tsx b/x-pack/plugins/maps/public/classes/layers/layer.tsx index 42fc01ad8475c..70cdc8ace4cf1 100644 --- a/x-pack/plugins/maps/public/classes/layers/layer.tsx +++ b/x-pack/plugins/maps/public/classes/layers/layer.tsx @@ -10,12 +10,18 @@ import { i18n } from '@kbn/i18n'; import type { Map as MbMap } from '@kbn/mapbox-gl'; import type { Query } from '@kbn/es-query'; +import { + getWarningsTitle, + type SearchResponseWarning, + ViewDetailsPopover, +} from '@kbn/search-response-warnings'; import _ from 'lodash'; import React, { ReactElement, ReactNode } from 'react'; import { EuiIcon } from '@elastic/eui'; import { v4 as uuidv4 } from 'uuid'; import { FeatureCollection } from 'geojson'; import { DataRequest } from '../util/data_request'; +import { hasIncompleteResults } from '../util/tile_meta_feature_utils'; import { LAYER_TYPE, MAX_ZOOM, @@ -41,9 +47,16 @@ import { LICENSED_FEATURES } from '../../licensed_features'; import { IESSource } from '../sources/es_source'; import { TileErrorsList } from './tile_errors_list'; -export interface LayerError { +export const INCOMPLETE_RESULTS_WARNING = i18n.translate( + 'xpack.maps.layer.incompleteResultsWarning', + { + defaultMessage: `Layer had issues returning data and results might be incomplete.`, + } +); + +export interface LayerMessage { title: string; - error: ReactNode; + body: ReactNode; } export interface ILayer { @@ -77,7 +90,9 @@ export interface ILayer { isLayerLoading(zoom: number): boolean; isFilteredByGlobalTime(): Promise; hasErrors(): boolean; - getErrors(): LayerError[]; + getErrors(): LayerMessage[]; + hasWarnings(): boolean; + getWarnings(): LayerMessage[]; /* * ILayer.getMbLayerIds returns a list of all mapbox layers assoicated with this layer. @@ -405,14 +420,14 @@ export class AbstractLayer implements ILayer { }); } - getErrors(): LayerError[] { - const errors: LayerError[] = []; + getErrors(): LayerMessage[] { + const errors: LayerMessage[] = []; - const sourceError = this.getSourceDataRequest()?.getError(); + const sourceError = this.getSourceDataRequest()?.renderError(); if (sourceError) { errors.push({ title: this._getSourceErrorTitle(), - error: sourceError, + body: sourceError, }); } @@ -421,13 +436,59 @@ export class AbstractLayer implements ILayer { title: i18n.translate('xpack.maps.layer.tileErrorTitle', { defaultMessage: `An error occurred when loading layer tiles`, }), - error: , + body: , }); } return errors; } + hasWarnings(): boolean { + const hasDataRequestWarnings = this._dataRequests.some((dataRequest) => { + const dataRequestMeta = dataRequest.getMeta(); + return dataRequestMeta?.warnings?.length; + }); + + if (hasDataRequestWarnings) { + return true; + } + + return this._isTiled() ? this._getTileMetaFeatures().some(hasIncompleteResults) : false; + } + + getWarnings(): LayerMessage[] { + const warningMessages: LayerMessage[] = []; + + const dataRequestWarnings: SearchResponseWarning[] = []; + this._dataRequests.forEach((dataRequest) => { + const dataRequestMeta = dataRequest.getMeta(); + if (dataRequestMeta?.warnings?.length) { + dataRequestWarnings.push(...dataRequestMeta.warnings); + } + }); + + if (dataRequestWarnings.length) { + warningMessages.push({ + title: getWarningsTitle(dataRequestWarnings), + body: ( + <> + {INCOMPLETE_RESULTS_WARNING}{' '} + + + ), + }); + } + + if (this._isTiled() && this._getTileMetaFeatures().some(hasIncompleteResults)) { + warningMessages.push({ + title: '', + body: INCOMPLETE_RESULTS_WARNING, + }); + } + + return warningMessages; + } + async syncData(syncContext: DataRequestContext) { // no-op by default } diff --git a/x-pack/plugins/maps/public/classes/layers/layer_group/layer_group.tsx b/x-pack/plugins/maps/public/classes/layers/layer_group/layer_group.tsx index 7b7ac229f154e..7bdab791f59f9 100644 --- a/x-pack/plugins/maps/public/classes/layers/layer_group/layer_group.tsx +++ b/x-pack/plugins/maps/public/classes/layers/layer_group/layer_group.tsx @@ -28,7 +28,7 @@ import { import { ISource, SourceEditorArgs } from '../../sources/source'; import { type DataRequestContext } from '../../../actions'; import { getLayersExtent } from '../../../actions/get_layers_extent'; -import { ILayer, LayerIcon, LayerError } from '../layer'; +import { ILayer, LayerIcon, LayerMessage } from '../layer'; import { IStyle } from '../../styles/style'; import { LICENSED_FEATURES } from '../../../licensed_features'; @@ -299,14 +299,33 @@ export class LayerGroup implements ILayer { }); } - getErrors(): LayerError[] { + getErrors(): LayerMessage[] { return this.hasErrors() ? [ { title: i18n.translate('xpack.maps.layerGroup.childrenErrorMessage', { defaultMessage: `An error occurred when loading nested layers`, }), - error: '', + body: '', + }, + ] + : []; + } + + hasWarnings(): boolean { + return this._children.some((child) => { + return child.hasWarnings(); + }); + } + + getWarnings(): LayerMessage[] { + return this.hasWarnings() + ? [ + { + title: i18n.translate('xpack.maps.layerGroup.incompleteResultsWarning', { + defaultMessage: `Nested layer(s) had issues returning data and results might be incomplete.`, + }), + body: '', }, ] : []; diff --git a/x-pack/plugins/maps/public/classes/layers/raster_tile_layer/raster_tile_layer.ts b/x-pack/plugins/maps/public/classes/layers/raster_tile_layer/raster_tile_layer.ts index e0666b6b05960..9decff440ee49 100644 --- a/x-pack/plugins/maps/public/classes/layers/raster_tile_layer/raster_tile_layer.ts +++ b/x-pack/plugins/maps/public/classes/layers/raster_tile_layer/raster_tile_layer.ts @@ -99,7 +99,7 @@ export class RasterTileLayer extends AbstractLayer { }; stopLoading(SOURCE_DATA_REQUEST_ID, requestToken, data, {}); } catch (error) { - onLoadError(SOURCE_DATA_REQUEST_ID, requestToken, error.message); + onLoadError(SOURCE_DATA_REQUEST_ID, requestToken, error); } } diff --git a/x-pack/plugins/maps/public/classes/layers/vector_layer/blended_vector_layer/blended_vector_layer.ts b/x-pack/plugins/maps/public/classes/layers/vector_layer/blended_vector_layer/blended_vector_layer.ts index 4efa00c6c8ad3..fec564c838bd6 100644 --- a/x-pack/plugins/maps/public/classes/layers/vector_layer/blended_vector_layer/blended_vector_layer.ts +++ b/x-pack/plugins/maps/public/classes/layers/vector_layer/blended_vector_layer/blended_vector_layer.ts @@ -6,6 +6,7 @@ */ import { i18n } from '@kbn/i18n'; +import type { SearchResponseWarning } from '@kbn/search-response-warnings'; import { IVectorLayer } from '../vector_layer'; import { GeoJsonVectorLayer } from '../geojson_vector_layer'; import { IVectorStyle, VectorStyle } from '../../../styles/vector/vector_style'; @@ -183,7 +184,7 @@ export class BlendedVectorLayer extends GeoJsonVectorLayer implements IVectorLay return layerDescriptor; } - private readonly _isClustered: boolean; + private _isClustered: boolean; private readonly _clusterSource: ESGeoGridSource; private readonly _clusterStyle: VectorStyle; private readonly _documentSource: ESSearchSource; @@ -313,21 +314,34 @@ export class BlendedVectorLayer extends GeoJsonVectorLayer implements IVectorLay let isSyncClustered; try { syncContext.startLoading(dataRequestId, requestToken, requestMeta); + const warnings: SearchResponseWarning[] = []; isSyncClustered = !(await this._documentSource.canLoadAllDocuments( + await this.getDisplayName(this._documentSource), requestMeta, - syncContext.registerCancelCallback.bind(null, requestToken) + syncContext.registerCancelCallback.bind(null, requestToken), + syncContext.inspectorAdapters, + (warning) => { + warnings.push(warning); + } )); - syncContext.stopLoading(dataRequestId, requestToken, { isSyncClustered }, requestMeta); + syncContext.stopLoading( + dataRequestId, + requestToken, + { isSyncClustered }, + { ...requestMeta, warnings } + ); } catch (error) { if (!(error instanceof DataRequestAbortError) || !isSearchSourceAbortError(error)) { - syncContext.onLoadError(dataRequestId, requestToken, error.message); + syncContext.onLoadError(dataRequestId, requestToken, error); } return; } if (isSyncClustered) { + this._isClustered = true; activeSource = this._clusterSource; activeStyle = this._clusterStyle; } else { + this._isClustered = false; activeSource = this._documentSource; activeStyle = this._documentStyle; } diff --git a/x-pack/plugins/maps/public/classes/layers/vector_layer/geojson_vector_layer/geojson_source_data.tsx b/x-pack/plugins/maps/public/classes/layers/vector_layer/geojson_vector_layer/geojson_source_data.tsx index 3550e93bb1595..272950de567eb 100644 --- a/x-pack/plugins/maps/public/classes/layers/vector_layer/geojson_vector_layer/geojson_source_data.tsx +++ b/x-pack/plugins/maps/public/classes/layers/vector_layer/geojson_vector_layer/geojson_source_data.tsx @@ -98,7 +98,7 @@ export async function syncGeojsonSourceData({ }; } catch (error) { if (!(error instanceof DataRequestAbortError)) { - onLoadError(dataRequestId, requestToken, error.message); + onLoadError(dataRequestId, requestToken, error); } throw error; } diff --git a/x-pack/plugins/maps/public/classes/layers/vector_layer/geojson_vector_layer/geojson_vector_layer.tsx b/x-pack/plugins/maps/public/classes/layers/vector_layer/geojson_vector_layer/geojson_vector_layer.tsx index 4faa32668f7de..30272f5038377 100644 --- a/x-pack/plugins/maps/public/classes/layers/vector_layer/geojson_vector_layer/geojson_vector_layer.tsx +++ b/x-pack/plugins/maps/public/classes/layers/vector_layer/geojson_vector_layer/geojson_vector_layer.tsx @@ -28,7 +28,7 @@ import { DataRequestContext } from '../../../../actions'; import { IVectorStyle, VectorStyle } from '../../../styles/vector/vector_style'; import { ISource } from '../../../sources/source'; import { IVectorSource } from '../../../sources/vector_source'; -import { AbstractLayer, LayerError, LayerIcon } from '../../layer'; +import { AbstractLayer, LayerMessage, LayerIcon } from '../../layer'; import { AbstractVectorLayer, noResultsIcon, @@ -158,7 +158,7 @@ export class GeoJsonVectorLayer extends AbstractVectorLayer { ); } - getErrors(): LayerError[] { + getErrors(): LayerMessage[] { const errors = super.getErrors(); this.getValidJoins().forEach((join) => { @@ -168,7 +168,7 @@ export class GeoJsonVectorLayer extends AbstractVectorLayer { title: i18n.translate('xpack.maps.geojsonVectorLayer.joinErrorTitle', { defaultMessage: `An error occurred when adding join metrics to layer features`, }), - error: joinDescriptor.error, + body: joinDescriptor.error, }); } }); diff --git a/x-pack/plugins/maps/public/classes/layers/vector_layer/geojson_vector_layer/perform_inner_joins.test.ts b/x-pack/plugins/maps/public/classes/layers/vector_layer/geojson_vector_layer/perform_inner_joins.test.ts index 70049304c9d9f..0fceb0729f818 100644 --- a/x-pack/plugins/maps/public/classes/layers/vector_layer/geojson_vector_layer/perform_inner_joins.test.ts +++ b/x-pack/plugins/maps/public/classes/layers/vector_layer/geojson_vector_layer/perform_inner_joins.test.ts @@ -81,8 +81,8 @@ const mockVectorSource = { }, } as unknown as IVectorSource; const innerJoin = new InnerJoin(joinDescriptor, mockVectorSource); -const propertiesMap = new Map>(); -propertiesMap.set('alpha', { [COUNT_PROPERTY_NAME]: 1 }); +const joinMetrics = new Map>(); +joinMetrics.set('alpha', { [COUNT_PROPERTY_NAME]: 1 }); test('should skip join when no state has changed', async () => { const updateSourceData = sinon.spy(); @@ -170,7 +170,7 @@ test('should call updateSourceData with feature collection with updated feature dataHasChanged: false, join: innerJoin, joinIndex: 0, - propertiesMap, + joinMetrics, }, ], updateSourceData, @@ -277,7 +277,7 @@ test('should call updateSourceData when no results returned from terms aggregati dataHasChanged: true, join: innerJoin, joinIndex: 0, - propertiesMap: new Map>(), + joinMetrics: new Map>(), }, ], updateSourceData, @@ -321,8 +321,8 @@ test('should call onJoinError when there are no matching features', async () => const setJoinError = sinon.spy(); // instead of returning military alphabet like "alpha" or "bravo", mismatched key returns numbers, like '1' - const propertiesMapFromMismatchedKey = new Map>(); - propertiesMapFromMismatchedKey.set('1', { [COUNT_PROPERTY_NAME]: 1 }); + const joinMetricsFromMismatchedKey = new Map>(); + joinMetricsFromMismatchedKey.set('1', { [COUNT_PROPERTY_NAME]: 1 }); await performInnerJoins( { @@ -334,7 +334,7 @@ test('should call onJoinError when there are no matching features', async () => dataHasChanged: true, join: innerJoin, joinIndex: 0, - propertiesMap: propertiesMapFromMismatchedKey, + joinMetrics: joinMetricsFromMismatchedKey, }, ], updateSourceData, diff --git a/x-pack/plugins/maps/public/classes/layers/vector_layer/geojson_vector_layer/perform_inner_joins.ts b/x-pack/plugins/maps/public/classes/layers/vector_layer/geojson_vector_layer/perform_inner_joins.ts index 55401c8edcb72..947aed099c9d9 100644 --- a/x-pack/plugins/maps/public/classes/layers/vector_layer/geojson_vector_layer/perform_inner_joins.ts +++ b/x-pack/plugins/maps/public/classes/layers/vector_layer/geojson_vector_layer/perform_inner_joins.ts @@ -59,8 +59,8 @@ export async function performInnerJoins( if (joinKey !== null) { joinStatus.keys.push(joinKey); } - const canJoinOnCurrent = joinState.propertiesMap - ? innerJoin.joinPropertiesToFeature(feature, joinState.propertiesMap) + const canJoinOnCurrent = joinState.joinMetrics + ? innerJoin.joinPropertiesToFeature(feature, joinState.joinMetrics) : false; if (canJoinOnCurrent && !joinStatus.joinedWithAtLeastOneFeature) { joinStatus.joinedWithAtLeastOneFeature = true; @@ -108,8 +108,7 @@ async function getJoinError(joinStatus: { return; } - const hasTerms = - joinStatus.joinState.propertiesMap && joinStatus.joinState.propertiesMap.size > 0; + const hasTerms = joinStatus.joinState.joinMetrics && joinStatus.joinState.joinMetrics.size > 0; if (!hasTerms || joinStatus.joinedWithAtLeastOneFeature) { return; @@ -129,9 +128,7 @@ async function getJoinError(joinStatus: { leftFieldName, leftFieldValues: prettyPrintArray(joinStatus.keys), rightFieldName, - rightFieldValues: prettyPrintArray( - Array.from(joinStatus.joinState.propertiesMap!.keys()) - ), + rightFieldValues: prettyPrintArray(Array.from(joinStatus.joinState.joinMetrics!.keys())), }, }); } diff --git a/x-pack/plugins/maps/public/classes/layers/vector_layer/mvt_vector_layer/mvt_source_data.ts b/x-pack/plugins/maps/public/classes/layers/vector_layer/mvt_vector_layer/mvt_source_data.ts index 17a92fff97ff7..7b3f800fabc3f 100644 --- a/x-pack/plugins/maps/public/classes/layers/vector_layer/mvt_vector_layer/mvt_source_data.ts +++ b/x-pack/plugins/maps/public/classes/layers/vector_layer/mvt_vector_layer/mvt_source_data.ts @@ -97,6 +97,6 @@ export async function syncMvtSourceData({ }; syncContext.stopLoading(SOURCE_DATA_REQUEST_ID, requestToken, sourceData, {}); } catch (error) { - syncContext.onLoadError(SOURCE_DATA_REQUEST_ID, requestToken, error.message); + syncContext.onLoadError(SOURCE_DATA_REQUEST_ID, requestToken, error); } } diff --git a/x-pack/plugins/maps/public/classes/layers/vector_layer/types.ts b/x-pack/plugins/maps/public/classes/layers/vector_layer/types.ts index 05fc9dd98eacc..930d32fa53552 100644 --- a/x-pack/plugins/maps/public/classes/layers/vector_layer/types.ts +++ b/x-pack/plugins/maps/public/classes/layers/vector_layer/types.ts @@ -12,5 +12,5 @@ export interface JoinState { dataHasChanged: boolean; join: InnerJoin; joinIndex: number; - propertiesMap?: PropertiesMap; + joinMetrics?: PropertiesMap; } diff --git a/x-pack/plugins/maps/public/classes/layers/vector_layer/vector_layer.tsx b/x-pack/plugins/maps/public/classes/layers/vector_layer/vector_layer.tsx index 0d5a3afbd216f..0d60b2dc1b6bd 100644 --- a/x-pack/plugins/maps/public/classes/layers/vector_layer/vector_layer.tsx +++ b/x-pack/plugins/maps/public/classes/layers/vector_layer/vector_layer.tsx @@ -50,7 +50,7 @@ import { VectorStyleRequestMeta, } from '../../../../common/descriptor_types'; import { IVectorSource } from '../../sources/vector_source'; -import { LayerIcon, ILayer, LayerError } from '../layer'; +import { LayerIcon, ILayer, LayerMessage } from '../layer'; import { InnerJoin } from '../../joins/inner_join'; import { isSpatialJoin } from '../../joins/is_spatial_join'; import { IField } from '../../fields/field'; @@ -274,18 +274,18 @@ export class AbstractVectorLayer extends AbstractLayer implements IVectorLayer { }); } - getErrors(): LayerError[] { + getErrors(): LayerMessage[] { const errors = super.getErrors(); this.getValidJoins().forEach((join) => { const joinDataRequest = this.getDataRequest(join.getSourceDataRequestId()); - const error = joinDataRequest?.getError(); - if (error) { + const joinError = joinDataRequest?.renderError(); + if (joinError) { errors.push({ title: i18n.translate('xpack.maps.vectorLayer.joinFetchErrorTitle', { defaultMessage: `An error occurred when loading join metrics`, }), - error, + body: joinError, }); } }); @@ -469,7 +469,7 @@ export class AbstractVectorLayer extends AbstractLayer implements IVectorLayer { startLoading(dataRequestId, requestToken, nextMeta); const layerName = await this.getDisplayName(source); - const styleMeta = await (source as IESSource).loadStylePropsMeta({ + const { styleMeta, warnings } = await (source as IESSource).loadStylePropsMeta({ layerName, style, dynamicStyleProps, @@ -481,10 +481,10 @@ export class AbstractVectorLayer extends AbstractLayer implements IVectorLayer { executionContext: dataFilters.executionContext, }); - stopLoading(dataRequestId, requestToken, styleMeta, nextMeta); + stopLoading(dataRequestId, requestToken, styleMeta, { ...nextMeta, warnings }); } catch (error) { if (!(error instanceof DataRequestAbortError)) { - onLoadError(dataRequestId, requestToken, error.message); + onLoadError(dataRequestId, requestToken, error); } throw error; } @@ -554,7 +554,7 @@ export class AbstractVectorLayer extends AbstractLayer implements IVectorLayer { stopLoading(dataRequestId, requestToken, formatters, nextMeta); } catch (error) { - onLoadError(dataRequestId, requestToken, error.message); + onLoadError(dataRequestId, requestToken, error); throw error; } } @@ -605,31 +605,29 @@ export class AbstractVectorLayer extends AbstractLayer implements IVectorLayer { dataHasChanged: false, join, joinIndex, - propertiesMap: prevDataRequest?.getData() as PropertiesMap, + joinMetrics: prevDataRequest?.getData() as PropertiesMap, }; } try { startLoading(sourceDataId, requestToken, joinRequestMeta); - const leftSourceName = await this._source.getDisplayName(); - const propertiesMap = await joinSource.getPropertiesMap( + const { joinMetrics, warnings } = await joinSource.getJoinMetrics( joinRequestMeta, - leftSourceName, - join.getLeftField().getName(), + await this.getDisplayName(), registerCancelCallback.bind(null, requestToken), inspectorAdapters, featureCollection ); - stopLoading(sourceDataId, requestToken, propertiesMap); + stopLoading(sourceDataId, requestToken, joinMetrics, { warnings }); return { dataHasChanged: true, join, joinIndex, - propertiesMap, + joinMetrics, }; } catch (error) { if (!(error instanceof DataRequestAbortError)) { - onLoadError(sourceDataId, requestToken, `Join error: ${error.message}`); + onLoadError(sourceDataId, requestToken, error); } throw error; } @@ -727,7 +725,7 @@ export class AbstractVectorLayer extends AbstractLayer implements IVectorLayer { const supportsFeatureEditing = await source.supportsFeatureEditing(); stopLoading(dataRequestId, requestToken, { supportsFeatureEditing }); } catch (error) { - onLoadError(dataRequestId, requestToken, error.message); + onLoadError(dataRequestId, requestToken, error); throw error; } } diff --git a/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/es_geo_grid_source.tsx b/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/es_geo_grid_source.tsx index 85cfbd48a2a07..4acb400807ad0 100644 --- a/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/es_geo_grid_source.tsx +++ b/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/es_geo_grid_source.tsx @@ -14,6 +14,7 @@ import type { AggregationsCompositeAggregate, SearchResponse, } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import type { SearchResponseWarning } from '@kbn/search-response-warnings'; import type { KibanaExecutionContext } from '@kbn/core/public'; import { ISearchSource } from '@kbn/data-plugin/common/search/search_source'; import { DataView } from '@kbn/data-plugin/common'; @@ -43,7 +44,12 @@ import { DataRequestAbortError } from '../../util/data_request'; import { LICENSED_FEATURES } from '../../../licensed_features'; import { getHttp } from '../../../kibana_services'; -import { GetFeatureActionsArgs, GeoJsonWithMeta, IMvtVectorSource } from '../vector_source'; +import { + GetFeatureActionsArgs, + GeoJsonWithMeta, + IMvtVectorSource, + getLayerFeaturesRequestName, +} from '../vector_source'; import { DataFilters, ESGeoGridSourceDescriptor, @@ -281,6 +287,7 @@ export class ESGeoGridSource extends AbstractESAggSource implements IMvtVectorSo bufferedExtent, inspectorAdapters, executionContext, + onWarning, }: { searchSource: ISearchSource; searchSessionId?: string; @@ -293,6 +300,7 @@ export class ESGeoGridSource extends AbstractESAggSource implements IMvtVectorSo bufferedExtent: MapExtent; inspectorAdapters: Adapters; executionContext: KibanaExecutionContext; + onWarning: (warning: SearchResponseWarning) => void; }) { const gridsPerRequest: number = Math.floor(DEFAULT_MAX_BUCKETS_LIMIT / bucketsPerGrid); const aggs: any = { @@ -352,34 +360,16 @@ export class ESGeoGridSource extends AbstractESAggSource implements IMvtVectorSo : this.getId(); const esResponse: SearchResponse = await this._runEsQuery({ requestId, - requestName: i18n.translate('xpack.maps.source.esGrid.compositeInspector.requestName', { - defaultMessage: '{layerName} {bucketsName} composite request ({requestCount})', - values: { - bucketsName: this.getBucketsName(), - layerName, - requestCount, - }, - }), + requestName: getLayerFeaturesRequestName(`${layerName} (${requestCount})`), searchSource, registerCancelCallback, - requestDescription: i18n.translate( - 'xpack.maps.source.esGrid.compositeInspectorDescription', - { - defaultMessage: - 'Get {bucketsName} from data view: {dataViewName}, geospatial field: {geoFieldName}', - values: { - bucketsName: this.getBucketsName(), - dataViewName: indexPattern.getName(), - geoFieldName: this._descriptor.geoField, - }, - } - ), searchSessionId, executionContext: mergeExecutionContext( { description: 'es_geo_grid_source:cluster_composite' }, executionContext ), requestsAdapter: inspectorAdapters.requests, + onWarning, }); features.push(...convertCompositeRespToGeoJson(esResponse, this._descriptor.requestType)); @@ -406,6 +396,7 @@ export class ESGeoGridSource extends AbstractESAggSource implements IMvtVectorSo tooManyBuckets, inspectorAdapters, executionContext, + onWarning, }: { searchSource: ISearchSource; searchSessionId?: string; @@ -417,6 +408,7 @@ export class ESGeoGridSource extends AbstractESAggSource implements IMvtVectorSo tooManyBuckets: boolean; inspectorAdapters: Adapters; executionContext: KibanaExecutionContext; + onWarning: (warning: SearchResponseWarning) => void; }): Promise { const valueAggsDsl = tooManyBuckets ? this.getValueAggsDsl(indexPattern, (metric) => { @@ -446,30 +438,16 @@ export class ESGeoGridSource extends AbstractESAggSource implements IMvtVectorSo const esResponse = await this._runEsQuery({ requestId: this.getId(), - requestName: i18n.translate('xpack.maps.source.esGrid.inspector.requestName', { - defaultMessage: '{layerName} {bucketsName} request', - values: { - bucketsName: this.getBucketsName(), - layerName, - }, - }), + requestName: getLayerFeaturesRequestName(layerName), searchSource, registerCancelCallback, - requestDescription: i18n.translate('xpack.maps.source.esGrid.inspector.requestDescription', { - defaultMessage: - 'Get {bucketsName} from data view: {dataViewName}, geospatial field: {geoFieldName}', - values: { - bucketsName: this.getBucketsName(), - dataViewName: indexPattern.getName(), - geoFieldName: this._descriptor.geoField, - }, - }), searchSessionId, executionContext: mergeExecutionContext( { description: 'es_geo_grid_source:cluster' }, executionContext ), requestsAdapter: inspectorAdapters.requests, + onWarning, }); return convertRegularRespToGeoJson(esResponse, this._descriptor.requestType); @@ -516,6 +494,10 @@ export class ESGeoGridSource extends AbstractESAggSource implements IMvtVectorSo const supportsCompositeAgg = !(await this._isGeoShape()); const precision = this.getGeoGridPrecision(requestMeta.zoom); + const warnings: SearchResponseWarning[] = []; + const onWarning = (warning: SearchResponseWarning) => { + warnings.push(warning); + }; const features: Feature[] = supportsCompositeAgg && tooManyBuckets ? await this._compositeAggRequest({ @@ -530,6 +512,7 @@ export class ESGeoGridSource extends AbstractESAggSource implements IMvtVectorSo bufferedExtent: requestMeta.buffer, inspectorAdapters, executionContext: requestMeta.executionContext, + onWarning, }) : await this._nonCompositeAggRequest({ searchSource, @@ -542,6 +525,7 @@ export class ESGeoGridSource extends AbstractESAggSource implements IMvtVectorSo tooManyBuckets, inspectorAdapters, executionContext: requestMeta.executionContext, + onWarning, }); return { @@ -551,6 +535,7 @@ export class ESGeoGridSource extends AbstractESAggSource implements IMvtVectorSo }, meta: { areResultsTrimmed: false, + warnings, }, } as GeoJsonWithMeta; } diff --git a/x-pack/plugins/maps/public/classes/sources/es_geo_line_source/es_geo_line_source.tsx b/x-pack/plugins/maps/public/classes/sources/es_geo_line_source/es_geo_line_source.tsx index 24cafe66de35c..82bb8fec43234 100644 --- a/x-pack/plugins/maps/public/classes/sources/es_geo_line_source/es_geo_line_source.tsx +++ b/x-pack/plugins/maps/public/classes/sources/es_geo_line_source/es_geo_line_source.tsx @@ -11,6 +11,7 @@ import React from 'react'; import { GeoJsonProperties } from 'geojson'; import { i18n } from '@kbn/i18n'; import { type Filter, buildPhraseFilter } from '@kbn/es-query'; +import type { SearchResponseWarning } from '@kbn/search-response-warnings'; import { Adapters } from '@kbn/inspector-plugin/common/adapters'; import { EMPTY_FEATURE_COLLECTION, @@ -33,7 +34,7 @@ import { ESDocField } from '../../fields/es_doc_field'; import { InlineField } from '../../fields/inline_field'; import { UpdateSourceEditor } from './update_source_editor'; import { ImmutableSourceProperty, SourceEditorArgs } from '../source'; -import { GeoJsonWithMeta } from '../vector_source'; +import { GeoJsonWithMeta, getLayerFeaturesRequestName } from '../vector_source'; import { isValidStringConfig } from '../../util/valid_string_config'; import { IField } from '../../fields/field'; import { ITooltipProperty, TooltipProperty } from '../../tooltips/tooltip_property'; @@ -261,33 +262,21 @@ export class ESGeoLineSource extends AbstractESAggSource { }, }); + const warnings: SearchResponseWarning[] = []; const resp = await this._runEsQuery({ requestId: `${this.getId()}_tracks`, - requestName: i18n.translate('xpack.maps.source.esGeoLine.timeSeriesTrackRequestName', { - defaultMessage: `'{layerName}' tracks request (time series)`, - values: { - layerName, - }, - }), + requestName: getLayerFeaturesRequestName(layerName), searchSource, registerCancelCallback, - requestDescription: i18n.translate( - 'xpack.maps.source.esGeoLine.timeSeriesTrackRequestDescription', - { - defaultMessage: - 'Get tracks from data view: {dataViewName}, geospatial field: {geoFieldName}', - values: { - dataViewName: indexPattern.getName(), - geoFieldName: this._descriptor.geoField, - }, - } - ), searchSessionId: requestMeta.searchSessionId, executionContext: mergeExecutionContext( { description: 'es_geo_line:time_series_tracks' }, requestMeta.executionContext ), requestsAdapter: inspectorAdapters.requests, + onWarning: (warning: SearchResponseWarning) => { + warnings.push(warning); + }, }); const { featureCollection } = convertToGeoJson(resp, TIME_SERIES_ID_FIELD_NAME); @@ -303,7 +292,8 @@ export class ESGeoLineSource extends AbstractESAggSource { entityCount, numTrimmedTracks: 0, // geo_line by time series never truncates tracks and instead simplifies tracks totalEntities: resp?.aggregations?.totalEntities?.value ?? 0, - } as ESGeoLineSourceResponseMeta, + warnings, + }, }; } @@ -333,6 +323,7 @@ export class ESGeoLineSource extends AbstractESAggSource { } const indexPattern = await this.getIndexPattern(); + const warnings: SearchResponseWarning[] = []; // Request is broken into 2 requests // 1) fetch entities: filtered by buffer so that top entities in view are returned @@ -367,27 +358,22 @@ export class ESGeoLineSource extends AbstractESAggSource { const entityResp = await this._runEsQuery({ requestId: `${this.getId()}_entities`, requestName: i18n.translate('xpack.maps.source.esGeoLine.entityRequestName', { - defaultMessage: `'{layerName}' entities request`, + defaultMessage: `load track entities ({layerName})`, values: { layerName, }, }), searchSource: entitySearchSource, registerCancelCallback, - requestDescription: i18n.translate('xpack.maps.source.esGeoLine.entityRequestDescription', { - defaultMessage: - 'Get entities within map buffer from data view: {dataViewName}, entities: {splitFieldName}', - values: { - dataViewName: indexPattern.getName(), - splitFieldName: this._descriptor.splitField, - }, - }), searchSessionId: requestMeta.searchSessionId, executionContext: mergeExecutionContext( { description: 'es_geo_line:entities' }, requestMeta.executionContext ), requestsAdapter: inspectorAdapters.requests, + onWarning: (warning: SearchResponseWarning) => { + warnings.push(warning); + }, }); const entityBuckets: Array<{ key: string; doc_count: number }> = _.get( entityResp, @@ -446,29 +432,18 @@ export class ESGeoLineSource extends AbstractESAggSource { }); const tracksResp = await this._runEsQuery({ requestId: `${this.getId()}_tracks`, - requestName: i18n.translate('xpack.maps.source.esGeoLine.trackRequestName', { - defaultMessage: `'{layerName}' tracks request (terms)`, - values: { - layerName, - }, - }), + requestName: getLayerFeaturesRequestName(layerName), searchSource: tracksSearchSource, registerCancelCallback, - requestDescription: i18n.translate('xpack.maps.source.esGeoLine.trackRequestDescription', { - defaultMessage: - 'Get tracks for {numEntities} entities from data view: {dataViewName}, geospatial field: {geoFieldName}', - values: { - dataViewName: indexPattern.getName(), - geoFieldName: this._descriptor.geoField, - numEntities: entityBuckets.length, - }, - }), searchSessionId: requestMeta.searchSessionId, executionContext: mergeExecutionContext( { description: 'es_geo_line:terms_tracks' }, requestMeta.executionContext ), requestsAdapter: inspectorAdapters.requests, + onWarning: (warning: SearchResponseWarning) => { + warnings.push(warning); + }, }); const { featureCollection, numTrimmedTracks } = convertToGeoJson( tracksResp, @@ -487,7 +462,8 @@ export class ESGeoLineSource extends AbstractESAggSource { entityCount: entityBuckets.length, numTrimmedTracks, totalEntities, - } as ESGeoLineSourceResponseMeta, + warnings, + }, }; } diff --git a/x-pack/plugins/maps/public/classes/sources/es_pew_pew_source/es_pew_pew_source.tsx b/x-pack/plugins/maps/public/classes/sources/es_pew_pew_source/es_pew_pew_source.tsx index eaa6f0c716e19..9540a22bf6a4e 100644 --- a/x-pack/plugins/maps/public/classes/sources/es_pew_pew_source/es_pew_pew_source.tsx +++ b/x-pack/plugins/maps/public/classes/sources/es_pew_pew_source/es_pew_pew_source.tsx @@ -9,6 +9,7 @@ import React from 'react'; import turfBbox from '@turf/bbox'; import { multiPoint } from '@turf/helpers'; import { Adapters } from '@kbn/inspector-plugin/common/adapters'; +import type { SearchResponseWarning } from '@kbn/search-response-warnings'; import { type Filter, buildExistsFilter } from '@kbn/es-query'; import { lastValueFrom } from 'rxjs'; import type { @@ -34,7 +35,7 @@ import { VectorSourceRequestMeta, } from '../../../../common/descriptor_types'; import { isValidStringConfig } from '../../util/valid_string_config'; -import { BoundsRequestMeta, GeoJsonWithMeta } from '../vector_source'; +import { BoundsRequestMeta, GeoJsonWithMeta, getLayerFeaturesRequestName } from '../vector_source'; const MAX_GEOTILE_LEVEL = 29; @@ -188,29 +189,21 @@ export class ESPewPewSource extends AbstractESAggSource { buildExistsFilter({ name: this._descriptor.sourceGeoField, type: 'geo_point' }, indexPattern), ]); + const warnings: SearchResponseWarning[] = []; const esResponse = await this._runEsQuery({ requestId: this.getId(), - requestName: i18n.translate('xpack.maps.pewPew.requestName', { - defaultMessage: '{layerName} paths request', - values: { layerName }, - }), + requestName: getLayerFeaturesRequestName(layerName), searchSource, registerCancelCallback, - requestDescription: i18n.translate('xpack.maps.source.pewPew.inspectorDescription', { - defaultMessage: - 'Get paths from data view: {dataViewName}, source: {sourceFieldName}, destination: {destFieldName}', - values: { - dataViewName: indexPattern.getName(), - destFieldName: this._descriptor.destGeoField, - sourceFieldName: this._descriptor.sourceGeoField, - }, - }), searchSessionId: requestMeta.searchSessionId, executionContext: mergeExecutionContext( { description: 'es_pew_pew_source:connections' }, requestMeta.executionContext ), requestsAdapter: inspectorAdapters.requests, + onWarning: (warning: SearchResponseWarning) => { + warnings.push(warning); + }, }); const { featureCollection } = convertToLines(esResponse); @@ -219,6 +212,7 @@ export class ESPewPewSource extends AbstractESAggSource { data: featureCollection, meta: { areResultsTrimmed: false, + warnings, }, }; } diff --git a/x-pack/plugins/maps/public/classes/sources/es_search_source/es_search_source.tsx b/x-pack/plugins/maps/public/classes/sources/es_search_source/es_search_source.tsx index f56155284232d..77f4b684caf1f 100644 --- a/x-pack/plugins/maps/public/classes/sources/es_search_source/es_search_source.tsx +++ b/x-pack/plugins/maps/public/classes/sources/es_search_source/es_search_source.tsx @@ -9,6 +9,7 @@ import _ from 'lodash'; import React, { ReactElement } from 'react'; import type { QueryDslFieldLookup } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { i18n } from '@kbn/i18n'; +import type { SearchResponseWarning } from '@kbn/search-response-warnings'; import { GeoJsonProperties, Geometry, Position } from 'geojson'; import type { KibanaExecutionContext } from '@kbn/core/public'; import { type Filter, buildPhraseFilter, type TimeRange } from '@kbn/es-query'; @@ -58,6 +59,7 @@ import { import { ImmutableSourceProperty, SourceEditorArgs } from '../source'; import { IField } from '../../fields/field'; import { + getLayerFeaturesRequestName, GetFeatureActionsArgs, GeoJsonWithMeta, IMvtVectorSource, @@ -377,29 +379,21 @@ export class ESSearchSource extends AbstractESSource implements IMvtVectorSource } } + const warnings: SearchResponseWarning[] = []; const resp = await this._runEsQuery({ requestId: this.getId(), - requestName: i18n.translate('xpack.maps.esSearchSource.topHits.requestName', { - defaultMessage: '{layerName} top hits request', - values: { layerName }, - }), + requestName: getLayerFeaturesRequestName(layerName), searchSource, registerCancelCallback, - requestDescription: i18n.translate('xpack.maps.esSearchSource.topHits.requestDescription', { - defaultMessage: - 'Get top hits from data view: {dataViewName}, entities: {entitiesFieldName}, geospatial field: {geoFieldName}', - values: { - dataViewName: indexPattern.getName(), - entitiesFieldName: topHitsGroupByTimeseries ? '_tsid' : topHitsSplitFieldName, - geoFieldName: this._descriptor.geoField, - }, - }), searchSessionId: requestMeta.searchSessionId, executionContext: mergeExecutionContext( { description: 'es_search_source:top_hits' }, requestMeta.executionContext ), requestsAdapter: inspectorAdapters.requests, + onWarning: (warning: SearchResponseWarning) => { + warnings.push(warning); + }, }); const allHits: any[] = []; @@ -424,6 +418,7 @@ export class ESSearchSource extends AbstractESSource implements IMvtVectorSource areEntitiesTrimmed, entityCount: entityBuckets.length, totalEntities, + warnings, }, }; } @@ -435,6 +430,7 @@ export class ESSearchSource extends AbstractESSource implements IMvtVectorSource registerCancelCallback: (callback: () => void) => void, inspectorAdapters: Adapters ) { + const warnings: SearchResponseWarning[] = []; const indexPattern = await this.getIndexPattern(); const { docValueFields, sourceOnlyFields } = getDocValueAndSourceFields( @@ -451,7 +447,15 @@ export class ESSearchSource extends AbstractESSource implements IMvtVectorSource delete requestMetaWithoutTimeslice.timeslice; const useRequestMetaWithoutTimeslice = requestMeta.timeslice !== undefined && - (await this.canLoadAllDocuments(requestMetaWithoutTimeslice, registerCancelCallback)); + (await this.canLoadAllDocuments( + layerName, + requestMetaWithoutTimeslice, + registerCancelCallback, + inspectorAdapters, + (warning) => { + warnings.push(warning); + } + )); const maxResultWindow = await this.getMaxResultWindow(); const searchSource = await this.makeSearchSource( @@ -473,26 +477,18 @@ export class ESSearchSource extends AbstractESSource implements IMvtVectorSource const resp = await this._runEsQuery({ requestId: this.getId(), - requestName: i18n.translate('xpack.maps.esSearchSource.requestName', { - defaultMessage: '{layerName} documents request', - values: { layerName }, - }), + requestName: getLayerFeaturesRequestName(layerName), searchSource, registerCancelCallback, - requestDescription: i18n.translate('xpack.maps.esSearchSource.requestDescription', { - defaultMessage: - 'Get documents from data view: {dataViewName}, geospatial field: {geoFieldName}', - values: { - dataViewName: indexPattern.getName(), - geoFieldName: this._descriptor.geoField, - }, - }), searchSessionId: requestMeta.searchSessionId, executionContext: mergeExecutionContext( { description: 'es_search_source:doc_search' }, requestMeta.executionContext ), requestsAdapter: inspectorAdapters.requests, + onWarning: (warning: SearchResponseWarning) => { + warnings.push(warning); + }, }); const isTimeExtentForTimeslice = @@ -506,6 +502,7 @@ export class ESSearchSource extends AbstractESSource implements IMvtVectorSource ? requestMeta.timeslice : timerangeToTimeextent(requestMeta.timeFilters), isTimeExtentForTimeslice, + warnings, }, }; } @@ -990,25 +987,31 @@ export class ESSearchSource extends AbstractESSource implements IMvtVectorSource } async canLoadAllDocuments( + layerName: string, requestMeta: VectorSourceRequestMeta, - registerCancelCallback: (callback: () => void) => void + registerCancelCallback: (callback: () => void) => void, + inspectorAdapters: Adapters, + onWarning: (warning: SearchResponseWarning) => void ) { - const abortController = new AbortController(); - registerCancelCallback(() => abortController.abort()); const maxResultWindow = await this.getMaxResultWindow(); const searchSource = await this.makeSearchSource(requestMeta, 0); searchSource.setField('trackTotalHits', maxResultWindow + 1); - const { rawResponse: resp } = await lastValueFrom( - searchSource.fetch$({ - abortSignal: abortController.signal, - sessionId: requestMeta.searchSessionId, - legacyHitsTotal: false, - executionContext: mergeExecutionContext( - { description: 'es_search_source:all_doc_counts' }, - requestMeta.executionContext - ), - }) - ); + const resp = await this._runEsQuery({ + requestId: this.getId() + 'features_count', + requestName: i18n.translate('xpack.maps.vectorSource.featuresCountRequestName', { + defaultMessage: 'load features count ({layerName})', + values: { layerName }, + }), + searchSource, + registerCancelCallback, + searchSessionId: requestMeta.searchSessionId, + executionContext: mergeExecutionContext( + { description: 'es_search_source:all_doc_counts' }, + requestMeta.executionContext + ), + requestsAdapter: inspectorAdapters.requests, + onWarning, + }); return !isTotalHitsGreaterThan(resp.hits.total as unknown as TotalHits, maxResultWindow); } diff --git a/x-pack/plugins/maps/public/classes/sources/es_source/es_source.ts b/x-pack/plugins/maps/public/classes/sources/es_source/es_source.ts index 12941183aa502..2b5ec413ba6ec 100644 --- a/x-pack/plugins/maps/public/classes/sources/es_source/es_source.ts +++ b/x-pack/plugins/maps/public/classes/sources/es_source/es_source.ts @@ -15,13 +15,15 @@ import type { KibanaExecutionContext } from '@kbn/core/public'; import { RequestAdapter } from '@kbn/inspector-plugin/common/adapters/request'; import { lastValueFrom } from 'rxjs'; import type { TimeRange } from '@kbn/es-query'; +import { extractWarnings, type SearchResponseWarning } from '@kbn/search-response-warnings'; import type { IESAggSource } from '../es_agg_source'; import { AbstractVectorSource, BoundsRequestMeta } from '../vector_source'; import { getAutocompleteService, getIndexPatternService, - getTimeFilter, + getInspector, getSearchService, + getTimeFilter, } from '../../../kibana_services'; import { getDataViewNotFoundMessage } from '../../../../common/i18n_getters'; import { createExtentFilter } from '../../../../common/elasticsearch_util'; @@ -34,6 +36,7 @@ import { AbstractSourceDescriptor, DynamicStylePropertyOptions, MapExtent, + StyleMetaData, VectorSourceRequestMeta, } from '../../../../common/descriptor_types'; import { IVectorStyle } from '../../styles/vector/vector_style'; @@ -78,7 +81,7 @@ export interface IESSource extends IVectorSource { searchSessionId?: string; inspectorAdapters: Adapters; executionContext: KibanaExecutionContext; - }): Promise; + }): Promise<{ styleMeta: StyleMetaData; warnings: SearchResponseWarning[] }>; } export class AbstractESSource extends AbstractVectorSource implements IESSource { @@ -157,26 +160,28 @@ export class AbstractESSource extends AbstractVectorSource implements IESSource async _runEsQuery({ registerCancelCallback, - requestDescription, requestId, requestName, searchSessionId, searchSource, executionContext, requestsAdapter, + onWarning, }: { registerCancelCallback: (callback: () => void) => void; - requestDescription: string; requestId: string; requestName: string; searchSessionId?: string; searchSource: ISearchSource; executionContext: KibanaExecutionContext; requestsAdapter: RequestAdapter | undefined; + onWarning?: (warning: SearchResponseWarning) => void; }): Promise { const abortController = new AbortController(); registerCancelCallback(() => abortController.abort()); + const disableWarningToasts = onWarning !== undefined && requestsAdapter !== undefined; + try { const { rawResponse: resp } = await lastValueFrom( searchSource.fetch$({ @@ -187,23 +192,25 @@ export class AbstractESSource extends AbstractVectorSource implements IESSource adapter: requestsAdapter, id: requestId, title: requestName, - description: requestDescription, }, executionContext, + disableWarningToasts, }) ); + + if (disableWarningToasts) { + extractWarnings(resp, getInspector(), requestsAdapter, requestName, requestId).forEach( + onWarning + ); + } + return resp; } catch (error) { if (isSearchSourceAbortError(error)) { throw new DataRequestAbortError(); } - throw new Error( - i18n.translate('xpack.maps.source.esSource.requestFailedErrorMessage', { - defaultMessage: `Elasticsearch search request failed, error: {message}`, - values: { message: error.message }, - }) - ); + throw error; } } @@ -467,7 +474,7 @@ export class AbstractESSource extends AbstractVectorSource implements IESSource searchSessionId?: string; inspectorAdapters: Adapters; executionContext: KibanaExecutionContext; - }): Promise { + }) { const promises = dynamicStyleProps.map((dynamicStyleProp) => { return dynamicStyleProp.getFieldMetaRequest(); }); @@ -500,30 +507,30 @@ export class AbstractESSource extends AbstractVectorSource implements IESSource } } + const warnings: SearchResponseWarning[] = []; const resp = await this._runEsQuery({ requestId: `${this.getId()}_styleMeta`, requestName: i18n.translate('xpack.maps.source.esSource.stylePropsMetaRequestName', { - defaultMessage: '{layerName} - metadata', + defaultMessage: 'load symbolization ranges ({layerName})', values: { layerName }, }), searchSource, registerCancelCallback, - requestDescription: i18n.translate( - 'xpack.maps.source.esSource.stylePropsMetaRequestDescription', - { - defaultMessage: - 'Elasticsearch request retrieving field metadata used for calculating symbolization bands.', - } - ), searchSessionId, executionContext: mergeExecutionContext( { description: 'es_source:style_meta' }, executionContext ), requestsAdapter: inspectorAdapters.requests, + onWarning: (warning: SearchResponseWarning) => { + warnings.push(warning); + }, }); - return resp.aggregations; + return { + styleMeta: resp.aggregations, + warnings, + }; } getValueSuggestions = async (field: IField, query: string): Promise => { diff --git a/x-pack/plugins/maps/public/classes/sources/join_sources/es_distance_source/es_distance_source.ts b/x-pack/plugins/maps/public/classes/sources/join_sources/es_distance_source/es_distance_source.ts index 8bb3d903d61fe..e3cf6f7a1fda8 100644 --- a/x-pack/plugins/maps/public/classes/sources/join_sources/es_distance_source/es_distance_source.ts +++ b/x-pack/plugins/maps/public/classes/sources/join_sources/es_distance_source/es_distance_source.ts @@ -7,6 +7,7 @@ import { FeatureCollection } from 'geojson'; import { i18n } from '@kbn/i18n'; +import type { SearchResponseWarning } from '@kbn/search-response-warnings'; import type { Query } from '@kbn/es-query'; import { ISearchSource } from '@kbn/data-plugin/public'; import { Adapters } from '@kbn/inspector-plugin/common/adapters'; @@ -19,7 +20,6 @@ import { ESDistanceSourceDescriptor, VectorSourceRequestMeta, } from '../../../../../common/descriptor_types'; -import { PropertiesMap } from '../../../../../common/elasticsearch_util'; import { isValidStringConfig } from '../../../util/valid_string_config'; import { IJoinSource } from '../types'; import type { IESAggSource, ESAggsSourceSyncMeta } from '../../es_agg_source'; @@ -27,6 +27,7 @@ import { IField } from '../../../fields/field'; import { mergeExecutionContext } from '../../execution_context_utils'; import { processDistanceResponse } from './process_distance_response'; import { isSpatialSourceComplete } from '../is_spatial_source_complete'; +import { getJoinMetricsRequestName } from '../i18n_utils'; export const DEFAULT_WITHIN_DISTANCE = 5; @@ -80,14 +81,13 @@ export class ESDistanceSource extends AbstractESAggSource implements IJoinSource }); } - async getPropertiesMap( + async getJoinMetrics( requestMeta: VectorSourceRequestMeta, - leftSourceName: string, - leftFieldName: string, + layerName: string, registerCancelCallback: (callback: () => void) => void, inspectorAdapters: Adapters, featureCollection?: FeatureCollection - ): Promise { + ) { if (featureCollection === undefined) { throw new Error( i18n.translate('xpack.maps.esDistanceSource.noFeatureCollectionMsg', { @@ -97,7 +97,10 @@ export class ESDistanceSource extends AbstractESAggSource implements IJoinSource } if (!this.hasCompleteConfig()) { - return new Map(); + return { + joinMetrics: new Map(), + warnings: [], + }; } const distance = `${this._descriptor.distance}km`; @@ -119,7 +122,10 @@ export class ESDistanceSource extends AbstractESAggSource implements IJoinSource } if (!hasFilters) { - return new Map(); + return { + joinMetrics: new Map(), + warnings: [], + }; } const indexPattern = await this.getIndexPattern(); @@ -133,31 +139,27 @@ export class ESDistanceSource extends AbstractESAggSource implements IJoinSource aggs: this.getValueAggsDsl(indexPattern), }, }); + const warnings: SearchResponseWarning[] = []; const rawEsData = await this._runEsQuery({ requestId: this.getId(), - requestName: i18n.translate('xpack.maps.distanceSource.requestName', { - defaultMessage: '{leftSourceName} within distance join request', - values: { leftSourceName }, - }), + requestName: getJoinMetricsRequestName(layerName), searchSource, registerCancelCallback, - requestDescription: i18n.translate('xpack.maps.distanceSource.requestDescription', { - defaultMessage: - 'Get metrics from data view: {dataViewName}, geospatial field: {geoFieldName}', - values: { - dataViewName: indexPattern.getName(), - geoFieldName: this._descriptor.geoField, - }, - }), searchSessionId: requestMeta.searchSessionId, executionContext: mergeExecutionContext( { description: 'es_distance_source:distance_join_request' }, requestMeta.executionContext ), requestsAdapter: inspectorAdapters.requests, + onWarning: (warning: SearchResponseWarning) => { + warnings.push(warning); + }, }); - return processDistanceResponse(rawEsData, this.getAggKey(AGG_TYPE.COUNT)); + return { + joinMetrics: processDistanceResponse(rawEsData, this.getAggKey(AGG_TYPE.COUNT)), + warnings, + }; } isFilterByMapBounds(): boolean { diff --git a/x-pack/plugins/maps/public/classes/sources/join_sources/es_term_source/es_term_source.ts b/x-pack/plugins/maps/public/classes/sources/join_sources/es_term_source/es_term_source.ts index da477c76baab8..8a1978f6e7d96 100644 --- a/x-pack/plugins/maps/public/classes/sources/join_sources/es_term_source/es_term_source.ts +++ b/x-pack/plugins/maps/public/classes/sources/join_sources/es_term_source/es_term_source.ts @@ -6,6 +6,7 @@ */ import { i18n } from '@kbn/i18n'; +import type { SearchResponseWarning } from '@kbn/search-response-warnings'; import type { Query } from '@kbn/es-query'; import { ISearchSource } from '@kbn/data-plugin/public'; import { Adapters } from '@kbn/inspector-plugin/common/adapters'; @@ -36,6 +37,7 @@ import type { IESAggSource, ESAggsSourceSyncMeta } from '../../es_agg_source'; import { IField } from '../../../fields/field'; import { mergeExecutionContext } from '../../execution_context_utils'; import { isTermSourceComplete } from './is_term_source_complete'; +import { getJoinMetricsRequestName } from '../i18n_utils'; const TERMS_AGG_NAME = 'join'; const TERMS_BUCKET_KEYS_TO_IGNORE = ['key', 'doc_count']; @@ -125,15 +127,17 @@ export class ESTermSource extends AbstractESAggSource implements ITermJoinSource : super.getAggLabel(aggType, fieldLabel); } - async getPropertiesMap( + async getJoinMetrics( requestMeta: VectorSourceRequestMeta, - leftSourceName: string, - leftFieldName: string, + layerName: string, registerCancelCallback: (callback: () => void) => void, inspectorAdapters: Adapters - ): Promise { + ) { if (!this.hasCompleteConfig()) { - return new Map(); + return { + joinMetrics: new Map(), + warnings: [], + }; } const indexPattern = await this.getIndexPattern(); @@ -150,31 +154,28 @@ export class ESTermSource extends AbstractESAggSource implements ITermJoinSource }, }); + const warnings: SearchResponseWarning[] = []; const rawEsData = await this._runEsQuery({ requestId: this.getId(), - requestName: i18n.translate('xpack.maps.termSource.requestName', { - defaultMessage: '{leftSourceName} term join request', - values: { leftSourceName }, - }), + requestName: getJoinMetricsRequestName(layerName), searchSource, registerCancelCallback, - requestDescription: i18n.translate('xpack.maps.termSource.requestDescription', { - defaultMessage: 'Get metrics from data view: {dataViewName}, term field: {termFieldName}', - values: { - dataViewName: indexPattern.getName(), - termFieldName: this._termField.getName(), - }, - }), searchSessionId: requestMeta.searchSessionId, executionContext: mergeExecutionContext( { description: 'es_term_source:terms' }, requestMeta.executionContext ), requestsAdapter: inspectorAdapters.requests, + onWarning: (warning: SearchResponseWarning) => { + warnings.push(warning); + }, }); const countPropertyName = this.getAggKey(AGG_TYPE.COUNT); - return extractPropertiesMap(rawEsData, countPropertyName); + return { + joinMetrics: extractPropertiesMap(rawEsData, countPropertyName), + warnings, + }; } isFilterByMapBounds(): boolean { diff --git a/x-pack/plugins/maps/public/classes/sources/join_sources/i18n_utils.ts b/x-pack/plugins/maps/public/classes/sources/join_sources/i18n_utils.ts new file mode 100644 index 0000000000000..354fcae53c3ae --- /dev/null +++ b/x-pack/plugins/maps/public/classes/sources/join_sources/i18n_utils.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 { i18n } from '@kbn/i18n'; + +export const getJoinMetricsRequestName = (layerName: string) => { + return i18n.translate('xpack.maps.joinSource.joinMetricsRequestName', { + defaultMessage: 'load join metrics ({layerName})', + values: { layerName }, + }); +}; diff --git a/x-pack/plugins/maps/public/classes/sources/join_sources/table_source/table_source.test.ts b/x-pack/plugins/maps/public/classes/sources/join_sources/table_source/table_source.test.ts index df9c11a99daa4..95b2b6fae1cd2 100644 --- a/x-pack/plugins/maps/public/classes/sources/join_sources/table_source/table_source.test.ts +++ b/x-pack/plugins/maps/public/classes/sources/join_sources/table_source/table_source.test.ts @@ -17,7 +17,7 @@ describe('TableSource', () => { }); }); - describe('getPropertiesMap', () => { + describe('getJoinMetrics', () => { it('should roll up results', async () => { const tableSource = new TableSource({ term: 'iso', @@ -53,18 +53,17 @@ describe('TableSource', () => { ], }); - const propertiesMap = await tableSource.getPropertiesMap( + const { joinMetrics } = await tableSource.getJoinMetrics( {} as unknown as VectorSourceRequestMeta, - 'a', - 'b', + 'layer1', () => {} ); - expect(propertiesMap.size).toEqual(2); - expect(propertiesMap.get('US')).toEqual({ + expect(joinMetrics.size).toEqual(2); + expect(joinMetrics.get('US')).toEqual({ population: 100, }); - expect(propertiesMap.get('CN')).toEqual({ + expect(joinMetrics.get('CN')).toEqual({ population: 400, }); }); diff --git a/x-pack/plugins/maps/public/classes/sources/join_sources/table_source/table_source.ts b/x-pack/plugins/maps/public/classes/sources/join_sources/table_source/table_source.ts index c1321649168a2..0fb24d198bf78 100644 --- a/x-pack/plugins/maps/public/classes/sources/join_sources/table_source/table_source.ts +++ b/x-pack/plugins/maps/public/classes/sources/join_sources/table_source/table_source.ts @@ -54,12 +54,11 @@ export class TableSource extends AbstractVectorSource implements ITermJoinSource return `table source ${uuidv4()}`; } - async getPropertiesMap( + async getJoinMetrics( requestMeta: VectorSourceRequestMeta, - leftSourceName: string, - leftFieldName: string, + layerName: string, registerCancelCallback: (callback: () => void) => void - ): Promise { + ) { const propertiesMap: PropertiesMap = new Map(); const columnNames = this._descriptor.__columns.map((column) => { @@ -86,7 +85,10 @@ export class TableSource extends AbstractVectorSource implements ITermJoinSource } } - return propertiesMap; + return { + joinMetrics: propertiesMap, + warnings: [], + }; } getTermField(): IField { diff --git a/x-pack/plugins/maps/public/classes/sources/join_sources/types.ts b/x-pack/plugins/maps/public/classes/sources/join_sources/types.ts index 06c87f3469ec8..74d124c6b979f 100644 --- a/x-pack/plugins/maps/public/classes/sources/join_sources/types.ts +++ b/x-pack/plugins/maps/public/classes/sources/join_sources/types.ts @@ -6,6 +6,7 @@ */ import { FeatureCollection, GeoJsonProperties } from 'geojson'; +import type { SearchResponseWarning } from '@kbn/search-response-warnings'; import type { KibanaExecutionContext } from '@kbn/core/public'; import { Query } from '@kbn/data-plugin/common/query'; import { Adapters } from '@kbn/inspector-plugin/common/adapters'; @@ -18,14 +19,16 @@ import { ISource } from '../source'; export interface IJoinSource extends ISource { hasCompleteConfig(): boolean; getWhereQuery(): Query | undefined; - getPropertiesMap( + getJoinMetrics( requestMeta: VectorSourceRequestMeta, - leftSourceName: string, - leftFieldName: string, + layerName: string, registerCancelCallback: (callback: () => void) => void, inspectorAdapters: Adapters, featureCollection?: FeatureCollection - ): Promise; + ): Promise<{ + joinMetrics: PropertiesMap; + warnings: SearchResponseWarning[]; + }>; /* * Use getSyncMeta to expose join configurations that require join data re-fetch when changed. diff --git a/x-pack/plugins/maps/public/classes/sources/vector_source/index.ts b/x-pack/plugins/maps/public/classes/sources/vector_source/index.ts index f2f834d1d55d0..e33a7c63ad246 100644 --- a/x-pack/plugins/maps/public/classes/sources/vector_source/index.ts +++ b/x-pack/plugins/maps/public/classes/sources/vector_source/index.ts @@ -6,4 +6,12 @@ */ export * from './vector_source'; +import { i18n } from '@kbn/i18n'; export type { IMvtVectorSource } from './mvt_vector_source'; + +export const getLayerFeaturesRequestName = (layerName: string) => { + return i18n.translate('xpack.maps.vectorSource.featuresRequestName', { + defaultMessage: 'load layer features ({layerName})', + values: { layerName }, + }); +}; diff --git a/x-pack/plugins/maps/public/classes/sources/vector_source/vector_source.tsx b/x-pack/plugins/maps/public/classes/sources/vector_source/vector_source.tsx index c4da68816d262..5adaf6ec20c42 100644 --- a/x-pack/plugins/maps/public/classes/sources/vector_source/vector_source.tsx +++ b/x-pack/plugins/maps/public/classes/sources/vector_source/vector_source.tsx @@ -29,7 +29,7 @@ import { AbstractSource, ISource } from '../source'; import { IField } from '../../fields/field'; import { DataFilters, - ESSearchSourceResponseMeta, + DataRequestMeta, MapExtent, Timeslice, VectorSourceRequestMeta, @@ -43,11 +43,9 @@ export interface SourceStatus { isDeprecated?: boolean; } -export type GeoJsonFetchMeta = ESSearchSourceResponseMeta; - export interface GeoJsonWithMeta { data: FeatureCollection; - meta?: GeoJsonFetchMeta; + meta?: DataRequestMeta; } export interface BoundsRequestMeta { diff --git a/x-pack/plugins/maps/public/classes/util/data_request.ts b/x-pack/plugins/maps/public/classes/util/data_request.tsx similarity index 63% rename from x-pack/plugins/maps/public/classes/util/data_request.ts rename to x-pack/plugins/maps/public/classes/util/data_request.tsx index 10d83100e5eca..3cb493f138441 100644 --- a/x-pack/plugins/maps/public/classes/util/data_request.ts +++ b/x-pack/plugins/maps/public/classes/util/data_request.tsx @@ -7,7 +7,10 @@ /* eslint-disable max-classes-per-file */ -import { DataRequestDescriptor, DataRequestMeta } from '../../../common/descriptor_types'; +import React, { ReactNode } from 'react'; +import { getSearchErrorOverrideDisplay } from '@kbn/data-plugin/public'; +import { getApplication } from '../../kibana_services'; +import type { DataRequestDescriptor, DataRequestMeta } from '../../../common/descriptor_types'; export class DataRequest { private readonly _descriptor: DataRequestDescriptor; @@ -52,8 +55,30 @@ export class DataRequest { return this._descriptor.dataRequestToken; } - getError(): string | undefined { - return this._descriptor.error; + renderError(): ReactNode { + if (!this._descriptor.error) { + return null; + } + + const overrideDisplay = getSearchErrorOverrideDisplay({ + error: this._descriptor.error, + application: getApplication(), + }); + + const body = overrideDisplay?.body ? ( + overrideDisplay.body + ) : ( +

    {this._descriptor.error.message}

    + ); + + return overrideDisplay?.actions ? ( + <> + {body} + {overrideDisplay.actions} + + ) : ( + body + ); } } diff --git a/x-pack/plugins/maps/public/classes/util/tile_meta_feature_utils.test.ts b/x-pack/plugins/maps/public/classes/util/tile_meta_feature_utils.test.ts index c812dfa6b94f2..f8843c22f3893 100644 --- a/x-pack/plugins/maps/public/classes/util/tile_meta_feature_utils.test.ts +++ b/x-pack/plugins/maps/public/classes/util/tile_meta_feature_utils.test.ts @@ -6,7 +6,12 @@ */ import { TileMetaFeature } from '../../../common/descriptor_types'; -import { getAggsMeta, getAggRange, getHitsMeta } from './tile_meta_feature_utils'; +import { + getAggsMeta, + getAggRange, + getHitsMeta, + hasIncompleteResults, +} from './tile_meta_feature_utils'; describe('getAggsMeta', () => { test('should extract doc_count = 0 from meta features when there are no matches', () => { @@ -376,3 +381,73 @@ describe('getHitsMeta', () => { }); }); }); + +describe('hasIncompleteResults', () => { + const metaFeature = { + type: 'Feature', + geometry: { + type: 'Point', + coordinates: [0, 0], + }, + properties: { + '_clusters.skipped': 0, + '_clusters.partial': 0, + '_shards.failed': 0, + timed_out: false, + 'hits.total.relation': 'eq', + 'hits.total.value': 28, + }, + } as TileMetaFeature; + + test('should return false when all shards and clusters are successful', () => { + expect(hasIncompleteResults(metaFeature)).toBe(false); + }); + + test('should return true when local cluster has time out', () => { + expect( + hasIncompleteResults({ + ...metaFeature, + properties: { + ...metaFeature.properties, + timed_out: true, + }, + }) + ).toBe(true); + }); + + test('should return true when local cluster has shard failure', () => { + expect( + hasIncompleteResults({ + ...metaFeature, + properties: { + ...metaFeature.properties, + '_shards.failed': 1, + }, + }) + ).toBe(true); + }); + + test('should return true when remote cluster is skipped', () => { + expect( + hasIncompleteResults({ + ...metaFeature, + properties: { + ...metaFeature.properties, + '_clusters.skipped': 1, + }, + }) + ).toBe(true); + }); + + test('should return true when remote cluster has shard failure', () => { + expect( + hasIncompleteResults({ + ...metaFeature, + properties: { + ...metaFeature.properties, + '_clusters.partial': 1, + }, + }) + ).toBe(true); + }); +}); diff --git a/x-pack/plugins/maps/public/classes/util/tile_meta_feature_utils.ts b/x-pack/plugins/maps/public/classes/util/tile_meta_feature_utils.ts index ac12399a2e011..0af0b64b77a53 100644 --- a/x-pack/plugins/maps/public/classes/util/tile_meta_feature_utils.ts +++ b/x-pack/plugins/maps/public/classes/util/tile_meta_feature_utils.ts @@ -68,3 +68,35 @@ export function getAggRange( } : null; } + +export function hasIncompleteResults(tileMetaFeature: TileMetaFeature) { + if ( + typeof tileMetaFeature.properties?.timed_out === 'boolean' && + tileMetaFeature.properties.timed_out + ) { + return true; + } + + if ( + typeof tileMetaFeature.properties?.['_shards.failed'] === 'number' && + tileMetaFeature.properties['_shards.failed'] > 0 + ) { + return true; + } + + if ( + typeof tileMetaFeature.properties?.['_clusters.skipped'] === 'number' && + tileMetaFeature.properties['_clusters.skipped'] > 0 + ) { + return true; + } + + if ( + typeof tileMetaFeature.properties?.['_clusters.partial'] === 'number' && + tileMetaFeature.properties['_clusters.partial'] > 0 + ) { + return true; + } + + return false; +} diff --git a/x-pack/plugins/maps/public/connected_components/right_side_controls/layer_control/__snapshots__/layer_control.test.tsx.snap b/x-pack/plugins/maps/public/connected_components/right_side_controls/layer_control/__snapshots__/layer_control.test.tsx.snap index 20395d0674511..81e0f8500451c 100644 --- a/x-pack/plugins/maps/public/connected_components/right_side_controls/layer_control/__snapshots__/layer_control.test.tsx.snap +++ b/x-pack/plugins/maps/public/connected_components/right_side_controls/layer_control/__snapshots__/layer_control.test.tsx.snap @@ -120,7 +120,7 @@ exports[`LayerControl isLayerTOCOpen Should render expand button 1`] = ` position="left" > @@ -135,7 +135,7 @@ exports[`LayerControl isLayerTOCOpen Should render expand button with error icon position="left" > @@ -150,7 +150,7 @@ exports[`LayerControl isLayerTOCOpen Should render expand button with loading ic position="left" > diff --git a/x-pack/plugins/maps/public/connected_components/right_side_controls/layer_control/expand_button.tsx b/x-pack/plugins/maps/public/connected_components/right_side_controls/layer_control/expand_button.tsx index f80a84dc6782d..75116d10bbf1a 100644 --- a/x-pack/plugins/maps/public/connected_components/right_side_controls/layer_control/expand_button.tsx +++ b/x-pack/plugins/maps/public/connected_components/right_side_controls/layer_control/expand_button.tsx @@ -10,12 +10,12 @@ import { EuiButtonEmpty, EuiIcon, EuiLoadingSpinner } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; interface Props { - hasErrors: boolean; + hasErrorsOrWarnings: boolean; isLoading: boolean; onClick: () => void; } -export function ExpandButton({ hasErrors, isLoading, onClick }: Props) { +export function ExpandButton({ hasErrorsOrWarnings, isLoading, onClick }: Props) { // isLoading indicates at least one layer is loading. // Expand button should never be disabled. // Not using EuiButton* with iconType props because EuiButton* disables button when isLoading prop is true. @@ -34,7 +34,7 @@ export function ExpandButton({ hasErrors, isLoading, onClick }: Props) { ) : ( - + )} ); diff --git a/x-pack/plugins/maps/public/connected_components/right_side_controls/layer_control/layer_control.test.tsx b/x-pack/plugins/maps/public/connected_components/right_side_controls/layer_control/layer_control.test.tsx index c0b0c13ada2d7..ed3235bf7af3b 100644 --- a/x-pack/plugins/maps/public/connected_components/right_side_controls/layer_control/layer_control.test.tsx +++ b/x-pack/plugins/maps/public/connected_components/right_side_controls/layer_control/layer_control.test.tsx @@ -71,6 +71,9 @@ describe('LayerControl', () => { hasErrors: () => { return false; }, + hasWarnings: () => { + return false; + }, isLayerLoading: () => { return true; }, @@ -86,6 +89,9 @@ describe('LayerControl', () => { hasErrors: () => { return true; }, + hasWarnings: () => { + return false; + }, isLayerLoading: () => { return false; }, diff --git a/x-pack/plugins/maps/public/connected_components/right_side_controls/layer_control/layer_control.tsx b/x-pack/plugins/maps/public/connected_components/right_side_controls/layer_control/layer_control.tsx index e1c34223483c8..b0fc2a7620bd4 100644 --- a/x-pack/plugins/maps/public/connected_components/right_side_controls/layer_control/layer_control.tsx +++ b/x-pack/plugins/maps/public/connected_components/right_side_controls/layer_control/layer_control.tsx @@ -52,8 +52,8 @@ export function LayerControl({ if (isScreenshotMode()) { return null; } - const hasErrors = layerList.some((layer) => { - return layer.hasErrors(); + const hasErrorsOrWarnings = layerList.some((layer) => { + return layer.hasErrors() || layer.hasWarnings(); }); const isLoading = layerList.some((layer) => { return layer.isLayerLoading(zoom); @@ -67,7 +67,11 @@ export function LayerControl({ })} position="left" > - + ); } diff --git a/x-pack/plugins/maps/public/connected_components/right_side_controls/layer_control/layer_toc/toc_entry/__snapshots__/toc_entry.test.tsx.snap b/x-pack/plugins/maps/public/connected_components/right_side_controls/layer_control/layer_toc/toc_entry/__snapshots__/toc_entry.test.tsx.snap index 9a7816a6de39c..f770aeed87494 100644 --- a/x-pack/plugins/maps/public/connected_components/right_side_controls/layer_control/layer_toc/toc_entry/__snapshots__/toc_entry.test.tsx.snap +++ b/x-pack/plugins/maps/public/connected_components/right_side_controls/layer_control/layer_toc/toc_entry/__snapshots__/toc_entry.test.tsx.snap @@ -478,9 +478,22 @@ exports[`TOCEntry props should display layer details when isLegendDetailsOpen is className="mapTocEntry__layerDetails" data-test-subj="mapLayerTOCDetailslayer_1" > -
    - TOC details mock -
    + { + const mockLayer = { + getErrors: () => { + return [ + { + title: 'simulated error', + body:
    , + }, + ]; + }, + getWarnings: () => { + return [ + { + title: 'simulated warning', + body:
    , + }, + ]; + }, + renderLegendDetails: () => { + return
    ; + }, + } as unknown as ILayer; + + test('Should only render errors when layer contains errors', () => { + render(); + screen.getByTestId('layer-error'); + const error = screen.queryByTestId('layer-error'); + expect(error).not.toBeNull(); + const warning = screen.queryByTestId('layer-warning'); + expect(warning).toBeNull(); + const legend = screen.queryByTestId('layer-legend'); + expect(legend).toBeNull(); + }); + + test('Should render warnings and legend when layer contains warnings', () => { + render( + { + return []; + }, + }} + /> + ); + const error = screen.queryByTestId('layer-error'); + expect(error).toBeNull(); + const warning = screen.queryByTestId('layer-warning'); + expect(warning).not.toBeNull(); + const legend = screen.queryByTestId('layer-legend'); + expect(legend).not.toBeNull(); + }); +}); diff --git a/x-pack/plugins/maps/public/connected_components/right_side_controls/layer_control/layer_toc/toc_entry/legend_details.tsx b/x-pack/plugins/maps/public/connected_components/right_side_controls/layer_control/layer_toc/toc_entry/legend_details.tsx new file mode 100644 index 0000000000000..1561d47aa4945 --- /dev/null +++ b/x-pack/plugins/maps/public/connected_components/right_side_controls/layer_control/layer_toc/toc_entry/legend_details.tsx @@ -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 React from 'react'; +import { EuiCallOut, EuiSpacer } from '@elastic/eui'; +import type { ILayer } from '../../../../../classes/layers/layer'; + +interface Props { + layer: ILayer; +} + +export function LegendDetails({ layer }: Props) { + const errors = layer.getErrors(); + if (errors.length) { + return ( + <> + {errors.map(({ title, body }, index) => ( +
    + + {body} + + +
    + ))} + + ); + } + + const warnings = layer.getWarnings(); + return warnings.length ? ( + <> + {warnings.map(({ title, body }, index) => ( +
    + + {body} + + +
    + ))} + {layer.renderLegendDetails()} + + ) : ( + layer.renderLegendDetails() + ); +} diff --git a/x-pack/plugins/maps/public/connected_components/right_side_controls/layer_control/layer_toc/toc_entry/toc_entry.tsx b/x-pack/plugins/maps/public/connected_components/right_side_controls/layer_control/layer_toc/toc_entry/toc_entry.tsx index eb77812d5b62e..488f9a64083db 100644 --- a/x-pack/plugins/maps/public/connected_components/right_side_controls/layer_control/layer_toc/toc_entry/toc_entry.tsx +++ b/x-pack/plugins/maps/public/connected_components/right_side_controls/layer_control/layer_toc/toc_entry/toc_entry.tsx @@ -9,14 +9,7 @@ import React, { Component } from 'react'; import classNames from 'classnames'; import type { DraggableProvidedDragHandleProps } from '@hello-pangea/dnd'; import { FormattedMessage } from '@kbn/i18n-react'; -import { - EuiIcon, - EuiButtonIcon, - EuiCallOut, - EuiConfirmModal, - EuiButtonEmpty, - EuiSpacer, -} from '@elastic/eui'; +import { EuiIcon, EuiButtonIcon, EuiConfirmModal, EuiButtonEmpty } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { TOCEntryActionsPopover } from './toc_entry_actions_popover'; import { @@ -25,6 +18,7 @@ import { EDIT_LAYER_SETTINGS_LABEL, FIT_TO_DATA_LABEL, } from './action_labels'; +import { LegendDetails } from './legend_details'; import { ILayer } from '../../../../../classes/layers/layer'; import { isLayerGroup } from '../../../../../classes/layers/layer_group'; @@ -111,7 +105,9 @@ export class TOCEntry extends Component { async _loadHasLegendDetails() { const hasLegendDetails = - (await this.props.layer.hasLegendDetails()) && + ((await this.props.layer.hasLegendDetails()) || + this.props.layer.hasErrors() || + this.props.layer.hasWarnings()) && this.props.layer.isVisible() && this.props.layer.showAtZoomLevel(this.props.zoom); if (this._isMounted && hasLegendDetails !== this.state.hasLegendDetails) { @@ -150,10 +146,6 @@ export class TOCEntry extends Component { this.props.toggleVisible(this.props.layer.getId()); }; - _getLayerErrors = () => { - return isLayerGroup(this.props.layer) ? [] : this.props.layer.getErrors(); - }; - _renderCancelModal() { if (!this.state.shouldShowModal) { return null; @@ -240,8 +232,7 @@ export class TOCEntry extends Component { } _renderDetailsToggle() { - const errors = this._getLayerErrors(); - if (this.props.isDragging || (!this.state.hasLegendDetails && errors.length === 0)) { + if (this.props.isDragging || !this.state.hasLegendDetails) { return null; } @@ -304,32 +295,6 @@ export class TOCEntry extends Component { ); } - _renderLegendDetails = () => { - if (!this.props.isLegendDetailsOpen) { - return null; - } - - const errors = this._getLayerErrors(); - - return this.state.hasLegendDetails || errors.length ? ( -
    - {errors.length - ? errors.map(({ title, error }, index) => ( -
    - - {error} - - -
    - )) - : this.props.layer.renderLegendDetails()} -
    - ) : null; - }; - _hightlightAsSelectedLayer() { if (this.props.isCombineLayer) { return false; @@ -365,7 +330,16 @@ export class TOCEntry extends Component { > {this._renderLayerHeader()} - {this._renderLegendDetails()} + {this.props.isLegendDetailsOpen && + this.state.hasLegendDetails && + !isLayerGroup(this.props.layer) ? ( +
    + +
    + ) : null} {this._renderDetailsToggle()} diff --git a/x-pack/plugins/maps/public/connected_components/right_side_controls/layer_control/layer_toc/toc_entry/toc_entry_button/toc_entry_button.tsx b/x-pack/plugins/maps/public/connected_components/right_side_controls/layer_control/layer_toc/toc_entry/toc_entry_button/toc_entry_button.tsx index 71d5a9f708497..ba832f2aa3210 100644 --- a/x-pack/plugins/maps/public/connected_components/right_side_controls/layer_control/layer_toc/toc_entry/toc_entry_button/toc_entry_button.tsx +++ b/x-pack/plugins/maps/public/connected_components/right_side_controls/layer_control/layer_toc/toc_entry/toc_entry_button/toc_entry_button.tsx @@ -9,7 +9,7 @@ import React, { Component, Fragment, ReactNode } from 'react'; import { EuiButtonEmpty, EuiIcon, EuiToolTip, EuiLoadingSpinner } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; -import { ILayer } from '../../../../../../classes/layers/layer'; +import { type ILayer, INCOMPLETE_RESULTS_WARNING } from '../../../../../../classes/layers/layer'; import { IVectorSource } from '../../../../../../classes/sources/vector_source'; import { isLayerGroup } from '../../../../../../classes/layers/layer_group'; @@ -18,12 +18,6 @@ interface Footnote { message?: string | null; } -interface IconAndTooltipContent { - icon?: ReactNode; - tooltipContent?: ReactNode; - footnotes: Footnote[]; -} - export interface ReduxStateProps { isUsingSearch: boolean; zoom: number; @@ -69,22 +63,35 @@ export class TOCEntryButton extends Component { } } - getIconAndTooltipContent(): IconAndTooltipContent { - if (this.props.layer.hasErrors()) { - return { - icon: ( - - ), - tooltipContent: this.props.layer - .getErrors() - .map(({ title }) =>
    {title}
    ), - footnotes: [], - }; + getIconAndTooltipContent(): { + icon?: ReactNode; + tooltipContent?: ReactNode; + footnotes: Footnote[]; + postScript?: string; + } { + const errors = this.props.layer.getErrors(); + if (errors.length) { + const errorIcon = ( + + ); + return isLayerGroup(this.props.layer) + ? { + icon: errorIcon, + footnotes: [], + postScript: errors[0].title, + } + : { + icon: errorIcon, + tooltipContent: this.props.layer + .getErrors() + .map(({ title }) =>
    {title}
    ), + footnotes: [], + }; } if (!this.props.layer.isVisible()) { @@ -118,10 +125,26 @@ export class TOCEntryButton extends Component { }; } - const { icon, tooltipContent } = this.props.layer.getLayerIcon(true); + const { icon: layerIcon, tooltipContent } = this.props.layer.getLayerIcon(true); + const warnings = this.props.layer.getWarnings(); + const icon = warnings.length ? ( + + ) : ( + layerIcon + ); if (isLayerGroup(this.props.layer)) { - return { icon, tooltipContent, footnotes: [] }; + return { + icon, + tooltipContent, + footnotes: [], + postScript: warnings.length ? warnings[0].title : undefined, + }; } const footnotes = []; @@ -158,11 +181,12 @@ export class TOCEntryButton extends Component { icon, tooltipContent, footnotes, + postScript: warnings.length ? INCOMPLETE_RESULTS_WARNING : undefined, }; } render() { - const { icon, tooltipContent, footnotes } = this.getIconAndTooltipContent(); + const { icon, tooltipContent, footnotes, postScript } = this.getIconAndTooltipContent(); const footnoteIcons = footnotes.map((footnote, index) => { return ( @@ -189,6 +213,9 @@ export class TOCEntryButton extends Component { {tooltipContent} {footnoteTooltipContent} + {postScript ? ( +

    {postScript}

    + ) : null}
    } data-test-subj="layerTocTooltip" diff --git a/x-pack/plugins/maps/public/inspector/vector_tile_adapter/components/get_tile_request.test.ts b/x-pack/plugins/maps/public/inspector/vector_tile_adapter/components/get_tile_request.test.ts index 922d45b2effc7..c8bb1a8fb81bc 100644 --- a/x-pack/plugins/maps/public/inspector/vector_tile_adapter/components/get_tile_request.test.ts +++ b/x-pack/plugins/maps/public/inspector/vector_tile_adapter/components/get_tile_request.test.ts @@ -126,6 +126,7 @@ test('Should return elasticsearch vector tile request for hits tiles', () => { type: 'long', }, }, + size: 10000, sort: [ { '@timestamp': { diff --git a/x-pack/plugins/maps/public/reducers/map/data_request_utils.ts b/x-pack/plugins/maps/public/reducers/map/data_request_utils.ts index 0fe5f2bce8d16..66384e112bcbc 100644 --- a/x-pack/plugins/maps/public/reducers/map/data_request_utils.ts +++ b/x-pack/plugins/maps/public/reducers/map/data_request_utils.ts @@ -51,7 +51,7 @@ export function stopDataRequest( requestToken: symbol, responseMeta?: DataRequestMeta, data?: object, - errorMessage?: string + error?: Error ): MapState { const dataRequest = getDataRequest(state, layerId, dataRequestId, requestToken); return dataRequest @@ -65,7 +65,7 @@ export function stopDataRequest( }, dataRequestMetaAtStart: undefined, dataRequestToken: undefined, // active data request, - error: errorMessage, + error, }) : state; } diff --git a/x-pack/plugins/maps/public/reducers/map/map.ts b/x-pack/plugins/maps/public/reducers/map/map.ts index 20590d8626481..d79d01f2b1847 100644 --- a/x-pack/plugins/maps/public/reducers/map/map.ts +++ b/x-pack/plugins/maps/public/reducers/map/map.ts @@ -193,7 +193,7 @@ export function map(state: MapState = DEFAULT_MAP_STATE, action: Record = { @@ -20,5 +19,7 @@ export const config: PluginConfigDescriptor = { schema: configSchema, }; -export const plugin = (initializerContext: PluginInitializerContext) => - new MapsPlugin(initializerContext); +export const plugin = async (initializerContext: PluginInitializerContext) => { + const { MapsPlugin } = await import('./plugin'); + return new MapsPlugin(initializerContext); +}; diff --git a/x-pack/plugins/maps/tsconfig.json b/x-pack/plugins/maps/tsconfig.json index 364a6d24473d6..86955eeea584a 100644 --- a/x-pack/plugins/maps/tsconfig.json +++ b/x-pack/plugins/maps/tsconfig.json @@ -74,6 +74,7 @@ "@kbn/content-management-table-list-view", "@kbn/serverless", "@kbn/logging", + "@kbn/search-response-warnings", ], "exclude": [ "target/**/*", diff --git a/x-pack/plugins/metrics_data_access/server/index.ts b/x-pack/plugins/metrics_data_access/server/index.ts index e76f2201b340a..1c79d5c5d423c 100644 --- a/x-pack/plugins/metrics_data_access/server/index.ts +++ b/x-pack/plugins/metrics_data_access/server/index.ts @@ -6,7 +6,6 @@ */ import { PluginInitializerContext } from '@kbn/core/server'; -import { MetricsDataPlugin } from './plugin'; export type { MetricsDataPluginSetup, @@ -20,6 +19,7 @@ export { metricsDataSourceSavedObjectName } from './saved_objects/metrics_data_s export { MetricsDataClient } from './client'; export { MetricsDataClientMock } from './client_mock'; -export function plugin(context: PluginInitializerContext) { +export async function plugin(context: PluginInitializerContext) { + const { MetricsDataPlugin } = await import('./plugin'); return new MetricsDataPlugin(context); } diff --git a/x-pack/plugins/ml/server/index.ts b/x-pack/plugins/ml/server/index.ts index 232df4ae7f1df..ea5a603741857 100644 --- a/x-pack/plugins/ml/server/index.ts +++ b/x-pack/plugins/ml/server/index.ts @@ -8,7 +8,6 @@ import type { PluginConfigDescriptor, PluginInitializerContext } from '@kbn/core/server'; import { type ConfigSchema } from '../common/constants/app'; import { configSchema } from './config_schema'; -import { MlServerPlugin } from './plugin'; export type { MlPluginSetup, MlPluginStart } from './plugin'; export type { DatafeedStats as MlDatafeedStats, @@ -38,4 +37,7 @@ export const config: PluginConfigDescriptor = { }, }; -export const plugin = (ctx: PluginInitializerContext) => new MlServerPlugin(ctx); +export const plugin = async (ctx: PluginInitializerContext) => { + const { MlServerPlugin } = await import('./plugin'); + return new MlServerPlugin(ctx); +}; diff --git a/x-pack/plugins/monitoring/server/config.test.ts b/x-pack/plugins/monitoring/server/config.test.ts index 0b4a4e1bb57db..64dcf3489a7f9 100644 --- a/x-pack/plugins/monitoring/server/config.test.ts +++ b/x-pack/plugins/monitoring/server/config.test.ts @@ -22,6 +22,7 @@ describe('config schema', () => { }, "enabled": true, }, + "enabled": true, "kibana": Object { "collection": Object { "enabled": true, diff --git a/x-pack/plugins/monitoring/server/config.ts b/x-pack/plugins/monitoring/server/config.ts index 70253f6d4690f..e5670bda2c82f 100644 --- a/x-pack/plugins/monitoring/server/config.ts +++ b/x-pack/plugins/monitoring/server/config.ts @@ -82,6 +82,7 @@ export const configSchema = schema.object({ enabled: schema.boolean({ defaultValue: true }), }), }), + enabled: schema.boolean({ defaultValue: true }), }); export class MonitoringElasticsearchConfig extends ElasticsearchConfig { diff --git a/x-pack/plugins/monitoring/server/index.ts b/x-pack/plugins/monitoring/server/index.ts index ca55aa0770499..f39af9fffe7d6 100644 --- a/x-pack/plugins/monitoring/server/index.ts +++ b/x-pack/plugins/monitoring/server/index.ts @@ -7,7 +7,6 @@ import { TypeOf } from '@kbn/config-schema'; import { PluginInitializerContext, PluginConfigDescriptor } from '@kbn/core/server'; -import { MonitoringPlugin } from './plugin'; import { configSchema } from './config'; import { deprecations } from './deprecations'; @@ -15,7 +14,10 @@ export type { KibanaSettingsCollector } from './kibana_monitoring/collectors'; export type { MonitoringConfig } from './config'; export type { MonitoringPluginSetup, IBulkUploader } from './types'; -export const plugin = (initContext: PluginInitializerContext) => new MonitoringPlugin(initContext); +export const plugin = async (initContext: PluginInitializerContext) => { + const { MonitoringPlugin } = await import('./plugin'); + return new MonitoringPlugin(initContext); +}; export const config: PluginConfigDescriptor> = { schema: configSchema, deprecations, diff --git a/x-pack/plugins/monitoring_collection/server/index.ts b/x-pack/plugins/monitoring_collection/server/index.ts index e6f15bd297dc8..8a795dbf802b6 100644 --- a/x-pack/plugins/monitoring_collection/server/index.ts +++ b/x-pack/plugins/monitoring_collection/server/index.ts @@ -7,15 +7,16 @@ import { TypeOf } from '@kbn/config-schema'; import { PluginInitializerContext, PluginConfigDescriptor } from '@kbn/core/server'; -import { MonitoringCollectionPlugin } from './plugin'; import { configSchema } from './config'; export type { MonitoringCollectionConfig } from './config'; export type { MonitoringCollectionSetup, MetricResult, Metric } from './plugin'; -export const plugin = (initContext: PluginInitializerContext) => - new MonitoringCollectionPlugin(initContext); +export const plugin = async (initContext: PluginInitializerContext) => { + const { MonitoringCollectionPlugin } = await import('./plugin'); + return new MonitoringCollectionPlugin(initContext); +}; export const config: PluginConfigDescriptor> = { schema: configSchema, }; diff --git a/x-pack/plugins/notifications/server/index.ts b/x-pack/plugins/notifications/server/index.ts index 9e8785d680de5..4c3afb14f7a57 100755 --- a/x-pack/plugins/notifications/server/index.ts +++ b/x-pack/plugins/notifications/server/index.ts @@ -6,13 +6,13 @@ */ import type { PluginInitializerContext } from '@kbn/core/server'; -import { NotificationsPlugin } from './plugin'; export { config } from './config'; // This exports static code and TypeScript types, // as well as, Kibana Platform `plugin()` initializer. export type { NotificationsPluginStart } from './types'; -export function plugin(initializerContext: PluginInitializerContext) { +export async function plugin(initializerContext: PluginInitializerContext) { + const { NotificationsPlugin } = await import('./plugin'); return new NotificationsPlugin(initializerContext); } diff --git a/x-pack/plugins/observability/public/components/custom_threshold/components/expression_row.tsx b/x-pack/plugins/observability/public/components/custom_threshold/components/expression_row.tsx index 44cac014d25f7..0f53594bd49e9 100644 --- a/x-pack/plugins/observability/public/components/custom_threshold/components/expression_row.tsx +++ b/x-pack/plugins/observability/public/components/custom_threshold/components/expression_row.tsx @@ -19,6 +19,7 @@ import { euiStyled } from '@kbn/kibana-react-plugin/common'; import { AggregationType, builtInComparators, + COMPARATORS, IErrorObject, ThresholdExpression, } from '@kbn/triggers-actions-ui-plugin/public'; @@ -30,8 +31,12 @@ import { CustomEquationEditor } from './custom_equation'; import { CUSTOM_EQUATION, LABEL_HELP_MESSAGE, LABEL_LABEL } from '../i18n_strings'; import { decimalToPct, pctToDecimal } from '../helpers/corrected_percent_convert'; +// Create a new object with COMPARATORS.NOT_BETWEEN removed as we use OUTSIDE_RANGE +const updatedBuiltInComparators = { ...builtInComparators }; +delete updatedBuiltInComparators[COMPARATORS.NOT_BETWEEN]; + const customComparators = { - ...builtInComparators, + ...updatedBuiltInComparators, [Comparator.OUTSIDE_RANGE]: { text: i18n.translate('xpack.observability.customThreshold.rule.alertFlyout.outsideRangeLabel', { defaultMessage: 'Is not between', diff --git a/x-pack/plugins/observability/public/components/custom_threshold/components/preview_chart/painless_tinymath_parser.test.ts b/x-pack/plugins/observability/public/components/custom_threshold/components/preview_chart/painless_tinymath_parser.test.ts new file mode 100644 index 0000000000000..bfc8cb955a2b8 --- /dev/null +++ b/x-pack/plugins/observability/public/components/custom_threshold/components/preview_chart/painless_tinymath_parser.test.ts @@ -0,0 +1,205 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import { PainlessTinyMathParser } from './painless_tinymath_parser'; + +describe('PainlessTinyMathParser', () => { + it('should parse a simple equation without aggregations A-Z ', () => { + const equation = '1 + 1'; + const parser = new PainlessTinyMathParser({ equation }); + expect(parser.parse()).toEqual('1+1'); + }); + it('should parse a simple equation with one aggregations A', () => { + const equation = '100 * A'; + const parser = new PainlessTinyMathParser({ + equation, + aggMap: { + A: 'average(system.cpu.system.pct)', + }, + }); + // ✅ checked with Lens Formula editor + expect(parser.parse()).toEqual('100*average(system.cpu.system.pct)'); + }); + it('should parse a simple equation with two aggregations A and B', () => { + const equation = '100 * A + B / 100'; + const parser = new PainlessTinyMathParser({ + equation, + aggMap: { + A: 'average(system.cpu.system.pct)', + B: 'average(system.cpu.user.pct)', + }, + }); + // ✅ checked with Lens Formula editor + expect(parser.parse()).toEqual( + '100*average(system.cpu.system.pct)+average(system.cpu.user.pct)/100' + ); + }); + it('should parse an equation with three aggregations A, B and C with parentheses', () => { + const equation = '100 * (A + B / 100) - C'; + const parser = new PainlessTinyMathParser({ + equation, + aggMap: { + A: 'average(system.cpu.system.pct)', + B: 'average(system.cpu.user.pct)', + C: 'average(system.cpu.cores)', + }, + }); + // ✅ checked with Lens Formula editor + expect(parser.parse()).toEqual( + '100*(average(system.cpu.system.pct)+average(system.cpu.user.pct)/100)-average(system.cpu.cores)' + ); + }); + it('should parse an equation with one condition', () => { + const equation = 'A > 0 ? 10 : 20'; + const parser = new PainlessTinyMathParser({ + equation, + aggMap: { + A: 'average(system.cpu.system.pct)', + }, + }); + // ✅ checked with Lens Formula editor + expect(parser.parse()).toEqual('ifelse(average(system.cpu.system.pct)>0, 10, 20)'); + }); + + it('should parse an equation with two condition one of them is a single chart', () => { + const equation = 'A > B || A ? 20 : 30'; + const parser = new PainlessTinyMathParser({ + equation, + aggMap: { + A: 'average(system.cpu.system.pct)', + B: 'average(system.cpu.user.pct)', + }, + }); + // ✅ checked with Lens Formula editor + expect(parser.parse()).toEqual( + 'ifelse(ifelse(average(system.cpu.system.pct)>average(system.cpu.user.pct),1,0) + ifelse(average(system.cpu.system.pct) > 0,1,0) > 0, 20, 30)' + ); + }); + it('should parse an equation with one condition that when TRUE is a condition', () => { + const equation = 'A > 0 ? B > 0 ? 10 : 20 : 30'; + const parser = new PainlessTinyMathParser({ + equation, + aggMap: { + A: 'average(system.cpu.system.pct)', + B: 'average(system.cpu.user.pct)', + }, + }); + // ✅ checked with Lens Formula editor + expect(parser.parse()).toEqual( + 'ifelse(average(system.cpu.system.pct)>0, ifelse(average(system.cpu.user.pct)>0, 10, 20), 30)' + ); + }); + it('should parse an equation with two condition with OR', () => { + const equation = 'A > 0 || B > 10 ? 100 : 30'; + const parser = new PainlessTinyMathParser({ + equation, + aggMap: { + A: 'average(system.cpu.system.pct)', + B: 'average(system.cpu.user.pct)', + }, + }); + // ✅ checked with Lens Formula editor + expect(parser.parse()).toEqual( + 'ifelse(ifelse(average(system.cpu.system.pct)>0,1,0) + ifelse(average(system.cpu.user.pct)>10,1,0) > 0, 100, 30)' + ); + }); + it('should parse an equation with two condition with AND', () => { + const equation = 'A > 0 && B > 10 ? 100 : 30'; + const parser = new PainlessTinyMathParser({ + equation, + aggMap: { + A: 'average(system.cpu.system.pct)', + B: 'average(system.cpu.user.pct)', + }, + }); + // ✅ checked with Lens Formula editor + expect(parser.parse()).toEqual( + 'ifelse(ifelse(average(system.cpu.system.pct)>0,1,0) * ifelse(average(system.cpu.user.pct)>10,1,0) > 0, 100, 30)' + ); + }); + it('should parse an equation with two condition with OR and NOT with parentheses', () => { + const equation = '!(A > 0) || B == 10 ? 100 : 30'; + const parser = new PainlessTinyMathParser({ + equation, + aggMap: { + A: 'average(system.cpu.system.pct)', + B: 'average(system.cpu.user.pct)', + }, + }); + // ✅ checked with Lens Formula editor + expect(parser.parse()).toEqual( + 'ifelse(ifelse(average(system.cpu.system.pct)>0,0,1) + ifelse(average(system.cpu.user.pct)==10,1,0) > 0, 100, 30)' + ); + }); + it('should parse an equation with three conditions with mix of OR and AND with parentheses', () => { + const equation = '(A > 0 || B == 10) && A < 200 ? 100 : 30'; + const parser = new PainlessTinyMathParser({ + equation, + aggMap: { + A: 'average(system.cpu.system.pct)', + B: 'average(system.cpu.user.pct)', + }, + }); + // ✅ checked with Lens Formula editor + expect(parser.parse()).toEqual( + 'ifelse(ifelse(average(system.cpu.system.pct)>0,1,0) + ifelse(average(system.cpu.user.pct)==10,1,0) * ifelse(average(system.cpu.system.pct)<200,1,0) > 0, 100, 30)' + ); + }); + it('should parse an equation with four conditions with mix of OR and AND with NOT and NOT EQUAL and parentheses where FALSE is a condition', () => { + const equation = '!(A > 0) || B !== 10 && !(A < 200 || B == 2) ? 100 : A == 10 ? 200 : 300'; + const parser = new PainlessTinyMathParser({ + equation, + aggMap: { + A: 'average(system.cpu.system.pct)', + B: 'average(system.cpu.user.pct)', + }, + }); + // ✅ checked with Lens Formula editor + expect(parser.parse()).toEqual( + 'ifelse(ifelse(average(system.cpu.system.pct)>0,0,1) + ifelse(average(system.cpu.user.pct)==10,0,1) * ifelse(average(system.cpu.system.pct)<200,0,1) + ifelse(average(system.cpu.user.pct)==2,1,0) > 0, 100, ifelse(average(system.cpu.system.pct)==10, 200, 300))' + ); + }); + + it('should parse a complex equation with many nested conditions and many aggregations', () => { + const equation = + 'A == 10 && F == 10 ? B == 20 ? C < 200 ? D > 200 ? 300 : A - D : B/C : 20 : A * C > C * D ? (A+B)/C > 100 ? D !== 20 ? 200 : 100 : 200 : B/C'; + const parser = new PainlessTinyMathParser({ + equation, + aggMap: { + A: 'average(system.cpu.system.pct)', + B: 'average(system.cpu.user.pct)', + C: 'average(system.cpu.total.pct)', + D: 'average(system.cpu.cores)', + E: 'count()', + F: 'sum(system.cpu.total.pct)', + }, + }); + // ✅ checked with Lens Formula editor + expect(parser.parse()).toEqual( + 'ifelse(ifelse(average(system.cpu.system.pct)==10,1,0) * ifelse(sum(system.cpu.total.pct)==10,1,0) > 0, ifelse(average(system.cpu.user.pct)==20, ifelse(average(system.cpu.total.pct)<200, ifelse(average(system.cpu.cores)>200, 300, average(system.cpu.system.pct)-average(system.cpu.cores)), average(system.cpu.user.pct)/average(system.cpu.total.pct)), 20), ifelse(average(system.cpu.system.pct)*average(system.cpu.total.pct)>average(system.cpu.total.pct)*average(system.cpu.cores), ifelse((average(system.cpu.system.pct)+average(system.cpu.user.pct))/average(system.cpu.total.pct)>100, ifelse(ifelse(average(system.cpu.cores)==20,0,1) > 0, 200, 100), 200), average(system.cpu.user.pct)/average(system.cpu.total.pct)))' + ); + }); + + it('should parse a complex equation with deeply nested conditions and many aggregations with parentheses', () => { + const equation = + 'A == 10 && (F == 10 || (B > 20 && B ==20) || D > 20) ? B == 20 ? C < 200 ? D > 200 ? 300 : A - D : B/C : 20 : A * C > C * D ? (A+B)/C > 100 ? D !== 20 ? 200 : 100 : 200 : B/C'; + const parser = new PainlessTinyMathParser({ + equation, + aggMap: { + A: 'average(system.cpu.system.pct)', + B: 'average(system.cpu.user.pct)', + C: 'average(system.cpu.total.pct)', + D: 'average(system.cpu.cores)', + E: 'count()', + F: 'sum(system.cpu.total.pct)', + }, + }); + // ✅ checked with Lens Formula editor + expect(parser.parse()).toEqual( + 'ifelse(ifelse(average(system.cpu.system.pct)==10,1,0) * ifelse(sum(system.cpu.total.pct)==10,1,0) + ifelse(average(system.cpu.user.pct)>20,1,0) * ifelse(average(system.cpu.user.pct)==20,1,0) + ifelse(average(system.cpu.cores)>20,1,0) > 0, ifelse(average(system.cpu.user.pct)==20, ifelse(average(system.cpu.total.pct)<200, ifelse(average(system.cpu.cores)>200, 300, average(system.cpu.system.pct)-average(system.cpu.cores)), average(system.cpu.user.pct)/average(system.cpu.total.pct)), 20), ifelse(average(system.cpu.system.pct)*average(system.cpu.total.pct)>average(system.cpu.total.pct)*average(system.cpu.cores), ifelse((average(system.cpu.system.pct)+average(system.cpu.user.pct))/average(system.cpu.total.pct)>100, ifelse(ifelse(average(system.cpu.cores)==20,0,1) > 0, 200, 100), 200), average(system.cpu.user.pct)/average(system.cpu.total.pct)))' + ); + }); +}); diff --git a/x-pack/plugins/observability/public/components/custom_threshold/components/preview_chart/painless_tinymath_parser.ts b/x-pack/plugins/observability/public/components/custom_threshold/components/preview_chart/painless_tinymath_parser.ts new file mode 100644 index 0000000000000..0bbcab23948ba --- /dev/null +++ b/x-pack/plugins/observability/public/components/custom_threshold/components/preview_chart/painless_tinymath_parser.ts @@ -0,0 +1,208 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +// This is a parser of a subset operations/expression/statement of Painless A-Z, +, -, /, *, (, ), ?, !, &, :, |, >, <, = to be used in Lens formula editor that uses TinyMath +// The goal is to parse painless expressions to a format that can be used in Lens formula editor +// The parser will also replace the characters A-Z with the values from aggMap +// Example: "A > 0 ? 10 : 20" will be parsed to "ifelse(average(system.cpu.system.pct) > 0, 10, 20)" +// Technically, this parser is NOT following the normal rules of parsing, means building AST, grammar file, tokenizer, and handling function, because it is a subset of Painless +// This parser is using a simple recursive function to parse the expression and replace the characters with the values from aggMap + +export interface AggMap { + [key: string]: string; +} +interface PainlessTinyMathParserProps { + equation: string; + aggMap?: AggMap; +} +export class PainlessTinyMathParser { + private IF = '?'; + private ELSE = ':'; + private AND = '&'; + private OR = '|'; + private NOT_EQUAL = '!='; + private NOT = '!'; + private openParenthesesRegex = /^\(*/g; + private notRegex = /^\!/g; + private closeParenthesesRegex = /\)*$/g; + private logicalConditionRegex = /(\s*[|&]{2})/g; + + private aggMap = {}; + private equation = ''; + + constructor({ equation, aggMap }: PainlessTinyMathParserProps) { + this.aggMap = aggMap || this.aggMap; + this.equation = this.clean(equation) || this.equation; + return this; + } + + clean(expression: string): string { + return expression + .replace(/(\s|\n)/g, '') + .replace('===', '==') + .replace('!==', '!='); + } + + diveIntoString( + expression: string, + levelDownChar: string, + levelUpChar: string + ): number | undefined { + // Search for the first ? and then start count the depth of the nest IFs + const expressionLength = expression.length; + let currentDepth = 0; + for (let i = expression.indexOf(levelDownChar); i < expressionLength; i++) { + const char = expression.charAt(i); + + if (char === levelDownChar) { + currentDepth += 1; + } + if (char === levelUpChar) { + currentDepth -= 1; + } + if (currentDepth === 0) { + return i; + } + // IT IS THE LAST CHAR AND THE DEPTH IS NOT 0, SO IT IS INVALID IF ELSE EXPRESSION + if (i === expressionLength - 1 && currentDepth !== 0) { + throw new Error('Invalid expression'); + } + } + } + + replaceCharactersWithAggMap(inputString: string, aggMap: AggMap): string { + // Use a regular expression to match any character from 'A' to 'Z' + const regex = /[A-Z]/g; + + return inputString.replace(regex, (match) => { + const replacement = aggMap[match]; // Get the replacement from the map + return replacement ? replacement : match; // Use the replacement or the original character + }); + } + + parseCondition(condition: string): string { + // If the condition does not contain any logical operators, return it as it is + if ( + !condition.includes(this.AND) && + !condition.includes(this.OR) && + !condition.includes(this.NOT_EQUAL) + ) { + return condition; + } + + const parts = condition.split(this.logicalConditionRegex); + const filteredParts = parts.filter((part) => part.trim() !== '' || part.includes(this.IF)); + const res = filteredParts.map((part) => { + // Handle the OR and AND cases and replace them with + and * + if (part.includes('||')) { + return part.replace('||', '+').trim(); + } + if (part.includes('&&')) { + return part.replace('&&', '*').trim(); + } + + // Handle the NOT and NOT_EQUAL cases and replace them with == and != + let isNOT = false; + if (part.includes(this.NOT)) isNOT = true; + if (part.includes(this.NOT_EQUAL)) { + part = part.replace('!=', '=='); + } + // Strip the part from the parentheses and the NOT characters + let stripedPart = part + .replace(this.notRegex, '') + .replace(this.openParenthesesRegex, '') + .replace(this.closeParenthesesRegex, '') + .replace(this.NOT, '') + .trim(); + // Build the ifelse function and switch the true/false position if it is a NOT case + // Every condition will be evaluated to 0 or 1 and then we will use the ifelse function to return the correct value + // example: ifelse(A > 0, 1, 0) example for NOT: ifelse(A > 0, 0, 1) + // If the condition is a single character e.g. A || B, we will add > 0 to it + if (/^[A-Z]$/.test(stripedPart)) { + stripedPart = stripedPart + ' > 0'; + } + let result = `ifelse(${stripedPart},${isNOT ? '0,1' : '1,0'})`; + + const openParentheses = part.match(this.openParenthesesRegex); + const closeParentheses = part.match(this.closeParenthesesRegex); + + // Ignore parentheses if they are opened and closed in the same condition as we put them using ifelse function + // Extra parentheses will throw error in Lens + // We keep the open parentheses and the closing parentheses that are not part of the same condition + if ( + openParentheses && + openParentheses.length > 0 && + closeParentheses && + closeParentheses.length > 0 + ) { + return result; + } + // Put back the open parentheses + if (openParentheses && openParentheses.length > 0) { + result = openParentheses[0] + result; + } + // Put back the closing parentheses + if (closeParentheses && closeParentheses.length > 0) { + result = result + closeParentheses[0]; + } + return result; + }); + + // At the end of the loop, we will have an array of conditions with AND(*) and OR(+) + // And to evaluate the whole condition, by wrapping them with ifelse and check if all the conditions are true (>0) + const conditions = res.join(' ') + ' > 0'; + return conditions; + } + + getTrueBranch(expression: string) { + const lastColonPosition = this.diveIntoString(expression, this.IF, this.ELSE); + if (lastColonPosition !== undefined) { + return expression.substring(expression.indexOf(this.IF) + 1, lastColonPosition); + } + return ''; + } + + getFalseBrach(expression: string) { + const lastColonPosition = this.diveIntoString(expression, this.IF, this.ELSE); + if (lastColonPosition !== undefined) { + return expression.substring(lastColonPosition + 1); + } + return ''; + } + + getCondition(expression: string): string { + return expression.substring(0, expression.indexOf(this.IF)); + } + + parse(): string { + const recursiveParseConditions = (expression: string): string => { + const condition = this.parseCondition(this.getCondition(expression)); + const trueBranch = this.getTrueBranch(expression); + const falseBranch = this.getFalseBrach(expression); + + let fullCondition = `ifelse(${condition}, ${trueBranch}, ${falseBranch})`; + + if (trueBranch.includes(this.IF)) { + const parsedTrueBranch = recursiveParseConditions(trueBranch); + fullCondition = fullCondition.replace(trueBranch, parsedTrueBranch); + } + if (falseBranch.includes(this.IF)) { + const parsedFalseBranch = recursiveParseConditions(falseBranch); + fullCondition = fullCondition.replace(falseBranch, parsedFalseBranch); + } + const result = this.replaceCharactersWithAggMap(fullCondition, this.aggMap); + return result; + }; + + if (!this.equation || this.equation === '') throw new Error('Invalid Equation'); + + if (this.equation.includes(this.IF)) { + return recursiveParseConditions(this.equation); + } + return this.replaceCharactersWithAggMap(this.equation, this.aggMap); + } +} diff --git a/x-pack/plugins/observability/public/components/custom_threshold/components/preview_chart/preview_chart.test.tsx b/x-pack/plugins/observability/public/components/custom_threshold/components/preview_chart/preview_chart.test.tsx new file mode 100644 index 0000000000000..9226da0ca2370 --- /dev/null +++ b/x-pack/plugins/observability/public/components/custom_threshold/components/preview_chart/preview_chart.test.tsx @@ -0,0 +1,74 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; +import { act } from 'react-dom/test-utils'; +import { DataView } from '@kbn/data-views-plugin/common'; +import { mountWithIntl, nextTick } from '@kbn/test-jest-helpers'; +import { CUSTOM_AGGREGATOR } from '../../../../../common/custom_threshold_rule/constants'; +import { Comparator, Aggregators } from '../../../../../common/custom_threshold_rule/types'; +import { useKibana } from '../../../../utils/kibana_react'; +import { kibanaStartMock } from '../../../../utils/kibana_react.mock'; +import { MetricExpression } from '../../types'; +import { PreviewChart } from './preview_chart'; + +jest.mock('../../../../utils/kibana_react'); + +const useKibanaMock = useKibana as jest.Mock; + +const mockKibana = () => { + useKibanaMock.mockReturnValue({ + ...kibanaStartMock.startContract(), + }); +}; + +describe('Preview chart', () => { + beforeEach(() => { + jest.clearAllMocks(); + mockKibana(); + }); + async function setup(expression: MetricExpression, dataView?: DataView) { + const wrapper = mountWithIntl( + + ); + + const update = async () => + await act(async () => { + await nextTick(); + wrapper.update(); + }); + + await update(); + + return { wrapper, update }; + } + + it('should display no data message', async () => { + const expression: MetricExpression = { + aggType: CUSTOM_AGGREGATOR, + metrics: [ + { + name: 'A', + aggType: Aggregators.COUNT, + }, + ], + timeSize: 1, + timeUnit: 'm', + sourceId: 'default', + threshold: [1], + comparator: Comparator.GT_OR_EQ, + }; + const { wrapper } = await setup(expression); + expect(wrapper.find('[data-test-subj="thresholdRuleNoChartData"]').exists()).toBeTruthy(); + }); +}); diff --git a/x-pack/plugins/observability/public/components/custom_threshold/components/preview_chart/preview_chart.tsx b/x-pack/plugins/observability/public/components/custom_threshold/components/preview_chart/preview_chart.tsx new file mode 100644 index 0000000000000..d5a8b763ca7b5 --- /dev/null +++ b/x-pack/plugins/observability/public/components/custom_threshold/components/preview_chart/preview_chart.tsx @@ -0,0 +1,339 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import React, { useState, useEffect } from 'react'; +import { EuiEmptyPrompt, useEuiTheme } from '@elastic/eui'; +import { FillStyle, OperationType } from '@kbn/lens-plugin/public'; +import { DataView } from '@kbn/data-views-plugin/common'; +import { FormattedMessage } from '@kbn/i18n-react'; +import useAsync from 'react-use/lib/useAsync'; +import { + LensAttributes, + LensAttributesBuilder, + XYChart, + XYDataLayer, + XYLayerOptions, + XYReferenceLinesLayer, +} from '@kbn/lens-embeddable-utils'; + +import { IErrorObject } from '@kbn/triggers-actions-ui-plugin/public'; +import { i18n } from '@kbn/i18n'; +import { + Aggregators, + Comparator, + AggType, +} from '../../../../../common/custom_threshold_rule/types'; +import { useKibana } from '../../../../utils/kibana_react'; +import { MetricExpression } from '../../types'; +import { AggMap, PainlessTinyMathParser } from './painless_tinymath_parser'; + +interface PreviewChartPros { + metricExpression: MetricExpression; + dataView?: DataView; + filterQuery?: string; + groupBy?: string | string[]; + error?: IErrorObject; +} + +const getOperationTypeFromRuleAggType = (aggType: AggType): OperationType => { + if (aggType === Aggregators.AVERAGE) return 'average'; + if (aggType === Aggregators.CARDINALITY) return 'unique_count'; + return aggType; +}; + +export function PreviewChart({ + metricExpression, + dataView, + filterQuery, + groupBy, + error, +}: PreviewChartPros) { + const { + services: { lens }, + } = useKibana(); + const { euiTheme } = useEuiTheme(); + const { metrics, timeSize, timeUnit, threshold, comparator, equation } = metricExpression; + const [attributes, setAttributes] = useState(); + const [aggMap, setAggMap] = useState(); + const [formula, setFormula] = useState(''); + const [thresholdReferenceLine, setThresholdReferenceLine] = useState(); + const [chartLoading, setChartLoading] = useState(false); + const formulaAsync = useAsync(() => { + return lens.stateHelperApi(); + }, [lens]); + + // Handle Lens error + useEffect(() => { + // Lens does not expose or provide a way to check if there is an error in the chart, yet. + // To work around this, we check if the element with class 'lnsEmbeddedError' is found in the DOM. + setTimeout(function () { + const errorDiv = document.querySelector('.lnsEmbeddedError'); + if (errorDiv) { + const paragraphElements = errorDiv.querySelectorAll('p'); + if (!paragraphElements || paragraphElements.length < 2) return; + paragraphElements[0].innerText = i18n.translate( + 'xpack.observability.customThreshold.rule..charts.error_equation.title', + { + defaultMessage: 'An error occurred while rendering the chart', + } + ); + paragraphElements[1].innerText = i18n.translate( + 'xpack.observability.customThreshold.rule..charts.error_equation.description', + { + defaultMessage: 'Check the rule equation.', + } + ); + } + }); + }, [chartLoading, attributes]); + + // Build the threshold reference line + useEffect(() => { + if (!threshold) return; + const refLayers = []; + const isPercent = Boolean(metrics.length === 1 && metrics[0].field?.endsWith('.pct')); + const format = { + id: isPercent ? 'percent' : 'number', + params: { + decimals: isPercent ? 0 : 2, + }, + }; + + if ( + comparator === Comparator.OUTSIDE_RANGE || + (comparator === Comparator.BETWEEN && threshold.length === 2) + ) { + const refLineStart = new XYReferenceLinesLayer({ + data: [ + { + value: (threshold[0] || 0).toString(), + color: euiTheme.colors.danger, + fill: comparator === Comparator.OUTSIDE_RANGE ? 'below' : 'above', + format, + }, + ], + }); + const refLineEnd = new XYReferenceLinesLayer({ + data: [ + { + value: (threshold[1] || 0).toString(), + color: euiTheme.colors.danger, + fill: comparator === Comparator.OUTSIDE_RANGE ? 'above' : 'below', + format, + }, + ], + }); + + refLayers.push(refLineStart, refLineEnd); + } else { + let fill: FillStyle = 'above'; + if (comparator === Comparator.LT || comparator === Comparator.LT_OR_EQ) { + fill = 'below'; + } + const thresholdRefLine = new XYReferenceLinesLayer({ + data: [ + { + value: (threshold[0] || 0).toString(), + color: euiTheme.colors.danger, + fill, + format, + }, + ], + }); + // A transparent line to add extra buffer at the top of threshold + const bufferRefLine = new XYReferenceLinesLayer({ + data: [ + { + value: Math.round((threshold[0] || 0) * 1.1).toString(), + color: 'transparent', + fill, + format, + }, + ], + }); + refLayers.push(thresholdRefLine, bufferRefLine); + } + setThresholdReferenceLine(refLayers); + }, [threshold, comparator, euiTheme.colors.danger, metrics]); + + // Build the aggregation map from the metrics + useEffect(() => { + if (!metrics || metrics.length === 0) { + return; + } + const aggMapFromMetrics = metrics.reduce((acc, metric) => { + const operation = getOperationTypeFromRuleAggType(metric.aggType); + let sourceField = metric.field; + + if (metric.aggType === Aggregators.COUNT) { + sourceField = '___records___'; + } + let operationField = `${operation}(${sourceField})`; + if (metric?.filter) { + const aggFilter = JSON.stringify(metric.filter).replace(/"|\\/g, ''); + operationField = `${operation}(${sourceField},kql='${aggFilter}')`; + } + return { + ...acc, + [metric.name]: operationField, + }; + }, {} as AggMap); + + setAggMap(aggMapFromMetrics); + }, [metrics]); + + // Parse the equation + useEffect(() => { + try { + if (!aggMap) return; + const parser = new PainlessTinyMathParser({ + aggMap, + equation: equation || Object.keys(aggMap || {}).join(' + '), + }); + + setFormula(parser.parse()); + } catch (e) { + // The error will appear on Lens chart. + setAttributes(undefined); + return; + } + }, [aggMap, equation]); + + useEffect(() => { + if (!formulaAsync.value || !dataView || !formula) { + return; + } + const isPercent = Boolean(metrics.length === 1 && metrics[0].field?.endsWith('.pct')); + const baseLayer = { + type: 'formula', + value: formula, + label: 'Custom Threshold', + groupBy, + format: { + id: isPercent ? 'percent' : 'number', + params: { + decimals: isPercent ? 0 : 2, + }, + }, + filter: { + language: 'kuery', + query: filterQuery || '', + }, + }; + + const xYDataLayerOptions: XYLayerOptions = { + buckets: { + type: 'date_histogram', + params: { + interval: `${timeSize}${timeUnit}`, + }, + }, + seriesType: 'bar', + }; + + if (groupBy && groupBy?.length) { + xYDataLayerOptions.breakdown = { + type: 'top_values', + field: groupBy[0], + params: { + size: 3, + secondaryFields: (groupBy as string[]).slice(1), + accuracyMode: false, + }, + }; + } + + const xyDataLayer = new XYDataLayer({ + data: [baseLayer].map((layer) => ({ + type: layer.type, + value: layer.value, + label: layer.label, + format: layer.format, + filter: layer.filter, + })), + options: xYDataLayerOptions, + }); + + const layers: Array = [xyDataLayer]; + if (thresholdReferenceLine) { + layers.push(...thresholdReferenceLine); + } + const attributesLens = new LensAttributesBuilder({ + visualization: new XYChart({ + visualOptions: { + valueLabels: 'hide', + axisTitlesVisibilitySettings: { + x: true, + yLeft: false, + yRight: true, + }, + }, + layers, + formulaAPI: formulaAsync.value.formula, + dataView, + }), + }).build(); + const lensBuilderAtt = { ...attributesLens, type: 'lens' }; + setAttributes(lensBuilderAtt); + }, [ + comparator, + dataView, + equation, + filterQuery, + formula, + formulaAsync.value, + groupBy, + metrics, + threshold, + thresholdReferenceLine, + timeSize, + timeUnit, + ]); + + if ( + !dataView || + !attributes || + error?.equation || + Object.keys(error?.metrics || {}).length !== 0 || + !timeSize + ) { + return ( +
    + + } + /> +
    + ); + } + return ( +
    + +
    + ); +} diff --git a/x-pack/plugins/observability/public/components/custom_threshold/custom_threshold_rule_expression.test.tsx b/x-pack/plugins/observability/public/components/custom_threshold/custom_threshold_rule_expression.test.tsx index 502f6a0ecd743..78fa6c3244427 100644 --- a/x-pack/plugins/observability/public/components/custom_threshold/custom_threshold_rule_expression.test.tsx +++ b/x-pack/plugins/observability/public/components/custom_threshold/custom_threshold_rule_expression.test.tsx @@ -18,6 +18,9 @@ import { kibanaStartMock } from '../../utils/kibana_react.mock'; import Expressions from './custom_threshold_rule_expression'; jest.mock('../../utils/kibana_react'); +jest.mock('./components/preview_chart/preview_chart', () => ({ + PreviewChart: jest.fn(() =>
    ), +})); const useKibanaMock = useKibana as jest.Mock; diff --git a/x-pack/plugins/observability/public/components/custom_threshold/custom_threshold_rule_expression.tsx b/x-pack/plugins/observability/public/components/custom_threshold/custom_threshold_rule_expression.tsx index 330d1c931cd09..2c5f7438b048f 100644 --- a/x-pack/plugins/observability/public/components/custom_threshold/custom_threshold_rule_expression.tsx +++ b/x-pack/plugins/observability/public/components/custom_threshold/custom_threshold_rule_expression.tsx @@ -40,9 +40,9 @@ import { CUSTOM_AGGREGATOR } from '../../../common/custom_threshold_rule/constan import { Aggregators, Comparator } from '../../../common/custom_threshold_rule/types'; import { TimeUnitChar } from '../../../common/utils/formatters/duration'; import { AlertContextMeta, AlertParams, MetricExpression } from './types'; -import { ExpressionChart } from './components/expression_chart'; import { ExpressionRow } from './components/expression_row'; import { MetricsExplorerFields, GroupBy } from './components/group_by'; +import { PreviewChart } from './components/preview_chart/preview_chart'; const FILTER_TYPING_DEBOUNCE_MS = 500; @@ -318,7 +318,6 @@ export default function Expressions(props: Props) { defaultMessage: 'Search for observability data… (e.g. host.name:host-1)', } ); - return ( <> @@ -412,13 +411,12 @@ export default function Expressions(props: Props) { expression={e || {}} dataView={derivedIndexPattern} > - {/* Preview */} -
    diff --git a/x-pack/plugins/observability/public/plugin.mock.tsx b/x-pack/plugins/observability/public/plugin.mock.tsx index 9732f67aac35f..6710b12dd6ca1 100644 --- a/x-pack/plugins/observability/public/plugin.mock.tsx +++ b/x-pack/plugins/observability/public/plugin.mock.tsx @@ -12,6 +12,7 @@ import { dataPluginMock } from '@kbn/data-plugin/public/mocks'; import { contentManagementMock } from '@kbn/content-management-plugin/public/mocks'; import { sharePluginMock } from '@kbn/share-plugin/public/mocks'; import { unifiedSearchPluginMock } from '@kbn/unified-search-plugin/public/mocks'; +import { lensPluginMock } from '@kbn/lens-plugin/public/mocks'; const triggersActionsUiStartMock = { createStart() { @@ -103,7 +104,7 @@ export const observabilityPublicPluginsStartMock = { dataViewEditor: dataViewEditor.createStart(), dataViews: dataViews.createStart(), discover: null, - lens: null, + lens: lensPluginMock.createStartContract(), share: sharePluginMock.createStartContract(), triggersActionsUi: triggersActionsUiStartMock.createStart(), unifiedSearch: unifiedSearchPluginMock.createStartContract(), diff --git a/x-pack/plugins/observability/server/index.ts b/x-pack/plugins/observability/server/index.ts index 2153d00abdbc6..ce2279db23203 100644 --- a/x-pack/plugins/observability/server/index.ts +++ b/x-pack/plugins/observability/server/index.ts @@ -10,7 +10,7 @@ import { offeringBasedSchema, schema, TypeOf } from '@kbn/config-schema'; import { PluginConfigDescriptor, PluginInitializerContext } from '@kbn/core/server'; -import { ObservabilityPlugin, ObservabilityPluginSetup } from './plugin'; +import type { ObservabilityPluginSetup } from './plugin'; import { createOrUpdateIndex, Mappings } from './utils/create_or_update_index'; import { createOrUpdateIndexTemplate } from './utils/create_or_update_index_template'; import { ScopedAnnotationsClient } from './lib/annotations/bootstrap_annotations'; @@ -75,8 +75,10 @@ export const config: PluginConfigDescriptor = { export type ObservabilityConfig = TypeOf; -export const plugin = (initContext: PluginInitializerContext) => - new ObservabilityPlugin(initContext); +export const plugin = async (initContext: PluginInitializerContext) => { + const { ObservabilityPlugin } = await import('./plugin'); + return new ObservabilityPlugin(initContext); +}; export type { Mappings, ObservabilityPluginSetup, ScopedAnnotationsClient }; export { diff --git a/x-pack/plugins/observability/tsconfig.json b/x-pack/plugins/observability/tsconfig.json index 2eeefa1b3165a..57a1deb071337 100644 --- a/x-pack/plugins/observability/tsconfig.json +++ b/x-pack/plugins/observability/tsconfig.json @@ -92,6 +92,7 @@ "@kbn/react-kibana-context-theme", "@kbn/shared-ux-link-redirect-app", "@kbn/core-chrome-browser", + "@kbn/lens-embeddable-utils", "@kbn/serverless", "@kbn/dashboard-plugin" ], diff --git a/x-pack/plugins/observability_ai_assistant/server/index.ts b/x-pack/plugins/observability_ai_assistant/server/index.ts index a6747758268b0..8660446357e34 100644 --- a/x-pack/plugins/observability_ai_assistant/server/index.ts +++ b/x-pack/plugins/observability_ai_assistant/server/index.ts @@ -7,7 +7,6 @@ import type { PluginConfigDescriptor, PluginInitializerContext } from '@kbn/core/server'; import type { ObservabilityAIAssistantConfig } from './config'; -import { ObservabilityAIAssistantPlugin } from './plugin'; export type { ObservabilityAIAssistantServerRouteRepository } from './routes/get_global_observability_ai_assistant_route_repository'; @@ -38,5 +37,7 @@ export const config: PluginConfigDescriptor = { schema: configSchema, }; -export const plugin = (ctx: PluginInitializerContext) => - new ObservabilityAIAssistantPlugin(ctx); +export const plugin = async (ctx: PluginInitializerContext) => { + const { ObservabilityAIAssistantPlugin } = await import('./plugin'); + return new ObservabilityAIAssistantPlugin(ctx); +}; diff --git a/x-pack/plugins/observability_log_explorer/README.md b/x-pack/plugins/observability_log_explorer/README.md index 604b33dd2b288..8e6f910f2da4e 100644 --- a/x-pack/plugins/observability_log_explorer/README.md +++ b/x-pack/plugins/observability_log_explorer/README.md @@ -1,3 +1,71 @@ # Observability Log Explorer This plugin provides an app based on the `LogExplorer` component from the `log_explorer` plugin, but adds observability-specific affordances. + +## Testing + +### Stateful + +#### FTR Server +``` +yarn test:ftr:server --config ./x-pack/test/functional/apps/observability_log_explorer/config.ts +``` + +#### FTR Runner +``` +yarn test:ftr:runner --config ./x-pack/test/functional/apps/observability_log_explorer/config.ts --include ./x-pack/test/functional/apps/observability_log_explorer/index.ts +``` + +#### Running Individual Tests +``` +yarn test:ftr:runner --config ./x-pack/test/functional/apps/observability_log_explorer/config.ts --include ./x-pack/test/functional/apps/observability_log_explorer/$1 +``` + +### Serverless + +#### Server +``` +yarn test:ftr:server --config ./x-pack/test_serverless/functional/test_suites/observability/config.ts +``` + +#### Runner +``` +yarn test:ftr:runner --config ./x-pack/test_serverless/functional/test_suites/observability/config.ts --include ./x-pack/test_serverless/functional/test_suites/observability/observability_log_explorer/index.ts +``` +#### Running Individual Tests +``` +yarn test:ftr:runner --config ./x-pack/test_serverless/functional/test_suites/observability/config.ts --include ./x-pack/test_serverless/functional/test_suites/observability/observability_log_explorer/$1 +``` + +## Checktypes + +#### Log Explorer +``` +node scripts/type_check.js --project x-pack/plugins/log_explorer/tsconfig.json +``` +#### Observability Log Explorer +``` +node scripts/type_check.js --project x-pack/plugins/observability_log_explorer/tsconfig.json +``` + +### Generating Data using Synthtrace + +#### Logs Data only +``` +node scripts/synthtrace simple_logs.ts --clean [--live] +``` + +#### Logs and Metrics Data +``` +node scripts/synthtrace logs_and_metrics.ts --clean [--live] +``` + +### General Issues + +#### Kibana CI broken due to `kbn/optimiser` issue ? + +The limit is done to protect us in case we add some dependency that heavily impacts the bundle size, so this is not to be intended as a fix, but as a conscious update after double-checking the bundle size increase and see if it can be reduced + +``` +node scripts/build_kibana_platform_plugins --focus logExplorer --update-limits +``` \ No newline at end of file diff --git a/x-pack/plugins/observability_log_explorer/server/index.ts b/x-pack/plugins/observability_log_explorer/server/index.ts index a487aefc8fd14..4d270d33f2e41 100644 --- a/x-pack/plugins/observability_log_explorer/server/index.ts +++ b/x-pack/plugins/observability_log_explorer/server/index.ts @@ -5,8 +5,9 @@ * 2.0. */ -import { ObservabilityLogExplorerServerPlugin } from './plugin'; - export { config } from './config'; -export const plugin = () => new ObservabilityLogExplorerServerPlugin(); +export const plugin = async () => { + const { ObservabilityLogExplorerServerPlugin } = await import('./plugin'); + return new ObservabilityLogExplorerServerPlugin(); +}; diff --git a/x-pack/plugins/observability_onboarding/server/index.ts b/x-pack/plugins/observability_onboarding/server/index.ts index ddc1c0ac79842..c22e7e92efdb9 100644 --- a/x-pack/plugins/observability_onboarding/server/index.ts +++ b/x-pack/plugins/observability_onboarding/server/index.ts @@ -10,7 +10,6 @@ import { PluginConfigDescriptor, PluginInitializerContext, } from '@kbn/core/server'; -import { ObservabilityOnboardingPlugin } from './plugin'; const configSchema = schema.object({ ui: schema.object({ @@ -35,7 +34,8 @@ export const config: PluginConfigDescriptor = { schema: configSchema, }; -export function plugin(initializerContext: PluginInitializerContext) { +export async function plugin(initializerContext: PluginInitializerContext) { + const { ObservabilityOnboardingPlugin } = await import('./plugin'); return new ObservabilityOnboardingPlugin(initializerContext); } diff --git a/x-pack/plugins/osquery/common/api/live_query/create_live_query_route.ts b/x-pack/plugins/osquery/common/api/live_query/create_live_query_route.ts index 462490fdbae96..bd2187ec9494e 100644 --- a/x-pack/plugins/osquery/common/api/live_query/create_live_query_route.ts +++ b/x-pack/plugins/osquery/common/api/live_query/create_live_query_route.ts @@ -13,6 +13,7 @@ import { packIdOrUndefined, queryOrUndefined, arrayQueries, + timeoutOrUndefined, } from '@kbn/osquery-io-ts-types'; export const createLiveQueryRequestBodySchema = t.partial({ @@ -23,6 +24,7 @@ export const createLiveQueryRequestBodySchema = t.partial({ query: queryOrUndefined, queries: arrayQueries, saved_query_id: savedQueryIdOrUndefined, + timeout: timeoutOrUndefined, ecs_mapping: ecsMappingOrUndefined, pack_id: packIdOrUndefined, alert_ids: t.array(t.string), diff --git a/x-pack/plugins/osquery/common/api/saved_query/create_saved_query_route.ts b/x-pack/plugins/osquery/common/api/saved_query/create_saved_query_route.ts index b55f9b62c02ed..22d70b6d284b0 100644 --- a/x-pack/plugins/osquery/common/api/saved_query/create_saved_query_route.ts +++ b/x-pack/plugins/osquery/common/api/saved_query/create_saved_query_route.ts @@ -18,6 +18,7 @@ import { snapshotOrUndefined, removedOrUndefined, ecsMappingOrUndefined, + timeoutOrUndefined, } from '@kbn/osquery-io-ts-types'; export const createSavedQueryRequestSchema = t.type({ @@ -27,6 +28,7 @@ export const createSavedQueryRequestSchema = t.type({ query, version: versionOrUndefined, interval, + timeout: timeoutOrUndefined, snapshot: snapshotOrUndefined, removed: removedOrUndefined, ecs_mapping: ecsMappingOrUndefined, diff --git a/x-pack/plugins/osquery/common/api/saved_query/update_saved_query_route.ts b/x-pack/plugins/osquery/common/api/saved_query/update_saved_query_route.ts index 274b52094b1b4..e13014c28bb0d 100644 --- a/x-pack/plugins/osquery/common/api/saved_query/update_saved_query_route.ts +++ b/x-pack/plugins/osquery/common/api/saved_query/update_saved_query_route.ts @@ -7,12 +7,14 @@ import * as t from 'io-ts'; import { toNumberRt } from '@kbn/io-ts-utils'; +import { timeoutOrUndefined } from '@kbn/osquery-io-ts-types'; export const updateSavedQueryRequestBodySchema = t.type({ id: t.string, query: t.string, description: t.union([t.string, t.undefined]), interval: t.union([toNumberRt, t.undefined]), + timeout: timeoutOrUndefined, snapshot: t.union([t.boolean, t.undefined]), removed: t.union([t.boolean, t.undefined]), platform: t.union([t.string, t.undefined]), diff --git a/x-pack/plugins/osquery/common/constants.ts b/x-pack/plugins/osquery/common/constants.ts index fe3454090277a..5887d783d4ce4 100644 --- a/x-pack/plugins/osquery/common/constants.ts +++ b/x-pack/plugins/osquery/common/constants.ts @@ -29,3 +29,8 @@ export const API_VERSIONS = { v1: '1', }, }; + +export enum QUERY_TIMEOUT { + DEFAULT = 60, // 60 seconds + MAX = 60 * 15, +} diff --git a/x-pack/plugins/osquery/common/search_strategy/osquery/actions/index.ts b/x-pack/plugins/osquery/common/search_strategy/osquery/actions/index.ts index 283ae46269422..7fd4ea5d31b2c 100644 --- a/x-pack/plugins/osquery/common/search_strategy/osquery/actions/index.ts +++ b/x-pack/plugins/osquery/common/search_strategy/osquery/actions/index.ts @@ -82,4 +82,5 @@ export interface ActionResultsStrategyResponse export interface ActionResultsRequestOptions extends RequestOptionsPaginated { actionId: string; + startDate?: string; } diff --git a/x-pack/plugins/osquery/common/search_strategy/osquery/index.ts b/x-pack/plugins/osquery/common/search_strategy/osquery/index.ts index 53508c17208b2..4ce3e0463696c 100644 --- a/x-pack/plugins/osquery/common/search_strategy/osquery/index.ts +++ b/x-pack/plugins/osquery/common/search_strategy/osquery/index.ts @@ -14,20 +14,17 @@ import type { ActionResultsStrategyResponse, ActionResultsRequestOptions, } from './actions'; -import type { AgentsStrategyResponse, AgentsRequestOptions } from './agents'; import type { ResultsStrategyResponse, ResultsRequestOptions } from './results'; import type { SortField, PaginationInputPaginated } from '../common'; export * from './actions'; -export * from './agents'; export * from './results'; export enum OsqueryQueries { actions = 'actions', actionDetails = 'actionDetails', actionResults = 'actionResults', - agents = 'agents', results = 'results', } @@ -54,8 +51,6 @@ export type StrategyResponseType = T extends Osquer ? ActionDetailsStrategyResponse : T extends OsqueryQueries.actionResults ? ActionResultsStrategyResponse - : T extends OsqueryQueries.agents - ? AgentsStrategyResponse : T extends OsqueryQueries.results ? ResultsStrategyResponse : never; @@ -66,8 +61,6 @@ export type StrategyRequestType = T extends Osquery ? ActionDetailsRequestOptions : T extends OsqueryQueries.actionResults ? ActionResultsRequestOptions - : T extends OsqueryQueries.agents - ? AgentsRequestOptions : T extends OsqueryQueries.results ? ResultsRequestOptions : never; diff --git a/x-pack/plugins/osquery/common/search_strategy/osquery/results/index.ts b/x-pack/plugins/osquery/common/search_strategy/osquery/results/index.ts index d7777e389dde8..c55577fb27354 100644 --- a/x-pack/plugins/osquery/common/search_strategy/osquery/results/index.ts +++ b/x-pack/plugins/osquery/common/search_strategy/osquery/results/index.ts @@ -21,5 +21,6 @@ export interface ResultsStrategyResponse extends IEsSearchResponse { export interface ResultsRequestOptions extends Omit { actionId: string; agentId?: string; + startDate?: string; sort: SortField[]; } diff --git a/x-pack/plugins/osquery/common/utils/aggregations.ts b/x-pack/plugins/osquery/common/utils/aggregations.ts new file mode 100644 index 0000000000000..c4afef4025ce5 --- /dev/null +++ b/x-pack/plugins/osquery/common/utils/aggregations.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 * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; + +interface BaseDataPoint { + key: string; + doc_count: number; +} + +interface AggDataPoint extends estypes.AggregationsTermsAggregateBase { + buckets: AggregationDataPoint[]; +} + +type AggregationDataPoint = BaseDataPoint & { + [key: string]: AggDataPoint; +}; + +interface Aggs extends estypes.AggregationsTermsAggregateBase { + buckets: AggregationDataPoint[]; +} + +interface Group { + id: string; + name: string; + size: number; +} + +interface Overlap { + [platform: string]: { [policy: string]: number }; +} + +export const processAggregations = ( + aggs: Record | undefined +) => { + if (!aggs) { + return { + platforms: [], + overlap: {}, + policies: [], + }; + } + + const platforms: Group[] = []; + const overlap: Overlap = {}; + const platformTerms = aggs.platforms as Aggs; + const policyTerms = aggs.policies as Aggs; + + const policies = + policyTerms?.buckets.map((o) => ({ name: o.key, id: o.key, size: o.doc_count })) ?? []; + + if (platformTerms?.buckets) { + for (const { key, doc_count: size, policies: platformPolicies } of platformTerms.buckets) { + platforms.push({ name: key, id: key, size }); + if (platformPolicies?.buckets && policies.length > 0) { + overlap[key] = platformPolicies.buckets.reduce((acc: { [key: string]: number }, pol) => { + acc[pol.key] = pol.doc_count; + + return acc; + }, {} as { [key: string]: number }); + } + } + } + + return { + platforms, + overlap, + policies, + }; +}; diff --git a/x-pack/plugins/osquery/cypress/e2e/all/live_query.cy.ts b/x-pack/plugins/osquery/cypress/e2e/all/live_query.cy.ts index 3e84dc001eed5..e43dbf4b5d487 100644 --- a/x-pack/plugins/osquery/cypress/e2e/all/live_query.cy.ts +++ b/x-pack/plugins/osquery/cypress/e2e/all/live_query.cy.ts @@ -8,6 +8,7 @@ import { navigateTo } from '../../tasks/navigation'; import { checkResults, + fillInQueryTimeout, inputQuery, selectAllAgents, submitQuery, @@ -36,13 +37,26 @@ describe('ALL - Live Query', { tags: ['@ess', '@serverless'] }, () => { cy.contains('Query is a required field').should('not.exist'); checkResults(); getAdvancedButton().click(); + fillInQueryTimeout('91'); + submitQuery(); + cy.contains('Timeout value must be lower than 900 seconds.'); + fillInQueryTimeout('89'); + submitQuery(); + cy.contains('Timeout value must be lower than 900 seconds.').should('not.exist'); typeInOsqueryFieldInput('days{downArrow}{enter}'); submitQuery(); cy.contains('ECS field is required.'); typeInECSFieldInput('message{downArrow}{enter}'); + + cy.intercept('POST', '/api/osquery/live_queries').as('postQuery'); submitQuery(); cy.contains('ECS field is required.').should('not.exist'); - + cy.wait('@postQuery').then((interception) => { + expect(interception.request.body).to.have.property('query', 'select * from uptime;'); + expect(interception.request.body).to.have.property('timeout', 890); + expect(interception.response?.statusCode).to.eq(200); + expect(interception.response?.body.data.queries[0]).to.have.property('timeout', 890); + }); checkResults(); cy.get('[data-gridcell-column-index="0"][data-gridcell-row-index="0"]').should('exist').click(); cy.url().should('include', 'app/fleet/agents/'); diff --git a/x-pack/plugins/osquery/cypress/e2e/all/live_query_packs.cy.ts b/x-pack/plugins/osquery/cypress/e2e/all/live_query_packs.cy.ts index da598382bf0ee..85ae94dd3266d 100644 --- a/x-pack/plugins/osquery/cypress/e2e/all/live_query_packs.cy.ts +++ b/x-pack/plugins/osquery/cypress/e2e/all/live_query_packs.cy.ts @@ -29,18 +29,21 @@ describe('ALL - Live Query Packs', { tags: ['@ess', '@serverless'] }, () => { system_memory_linux_elastic: { ecs_mapping: {}, interval: 3600, + timeout: 700, platform: 'linux', query: 'SELECT * FROM memory_info;', }, system_info_elastic: { ecs_mapping: {}, interval: 3600, + timeout: 200, platform: 'linux,windows,darwin', query: 'SELECT * FROM system_info;', }, failingQuery: { ecs_mapping: {}, interval: 10, + timeout: 90, query: 'select opera_extensions.* from users join opera_extensions using (uid);', }, }, diff --git a/x-pack/plugins/osquery/cypress/e2e/all/packs_create_edit.cy.ts b/x-pack/plugins/osquery/cypress/e2e/all/packs_create_edit.cy.ts index 32e2496f8ea06..ca83482cea37b 100644 --- a/x-pack/plugins/osquery/cypress/e2e/all/packs_create_edit.cy.ts +++ b/x-pack/plugins/osquery/cypress/e2e/all/packs_create_edit.cy.ts @@ -197,18 +197,21 @@ describe('Packs - Create and Edit', { tags: ['@ess', '@serverless'] }, () => { const queries = { Query1: { interval: 3600, + timeout: 60, query: 'select * from uptime;', removed: true, snapshot: false, }, Query2: { interval: 3600, + timeout: 60, query: 'select * from uptime;', removed: false, snapshot: false, }, Query3: { interval: 3600, + timeout: 60, query: 'select * from uptime;', }, }; diff --git a/x-pack/plugins/osquery/cypress/e2e/all/packs_integration.cy.ts b/x-pack/plugins/osquery/cypress/e2e/all/packs_integration.cy.ts index 30b8a1641fb94..9e10e1eb0d889 100644 --- a/x-pack/plugins/osquery/cypress/e2e/all/packs_integration.cy.ts +++ b/x-pack/plugins/osquery/cypress/e2e/all/packs_integration.cy.ts @@ -224,6 +224,7 @@ describe('ALL - Packs', { tags: ['@ess', '@serverless'] }, () => { cy.getBySel('createAgentPolicyNameField').type(agentPolicy); cy.getBySel('createAgentPolicyFlyoutBtn').click(); cy.contains(`Agent policy '${agentPolicy}' created`).click(); + closeToastIfVisible(); cy.contains(agentPolicy).click(); cy.contains('Add integration').click(); cy.getBySel('epmList.searchBar').type('osquery'); diff --git a/x-pack/plugins/osquery/cypress/tasks/live_query.ts b/x-pack/plugins/osquery/cypress/tasks/live_query.ts index d57f778e2c966..cc9319633befc 100644 --- a/x-pack/plugins/osquery/cypress/tasks/live_query.ts +++ b/x-pack/plugins/osquery/cypress/tasks/live_query.ts @@ -40,6 +40,12 @@ export const submitQuery = () => { cy.contains('Submit').click(); }; +export const fillInQueryTimeout = (timeout: string) => { + cy.getBySel('advanced-accordion-content').within(() => { + cy.getBySel('timeout-input').clear().type(timeout); + }); +}; + // sometimes the results get stuck in the tests, this is a workaround export const checkResults = () => { cy.getBySel('osqueryResultsTable').then(($table) => { diff --git a/x-pack/plugins/osquery/package.json b/x-pack/plugins/osquery/package.json index 4e9070d780d28..a708e9a383031 100644 --- a/x-pack/plugins/osquery/package.json +++ b/x-pack/plugins/osquery/package.json @@ -12,7 +12,7 @@ "cypress:run": "yarn cypress run", "cypress:serverless": "NODE_OPTIONS=--openssl-legacy-provider node ../security_solution/scripts/start_cypress_parallel --config-file ../osquery/cypress/serverless_cypress.config.ts --ftr-config-file ../../../x-pack/test/osquery_cypress/serverless_cli_config", "cypress:serverless:open": "yarn cypress:serverless open", - "cypress:serverless:run": "yarn cypress:serverless run", + "cypress:serverless:run": "yarn cypress:serverless run --spec ./cypress/e2e/all/packs_integration.cy.ts", "nyc": "../../../node_modules/.bin/nyc report --reporter=text-summary", "junit:merge": "../../../node_modules/.bin/mochawesome-merge ../../../target/kibana-osquery/cypress/results/mochawesome*.json > ../../../target/kibana-osquery/cypress/results/output.json && ../../../node_modules/.bin/marge ../../../target/kibana-osquery/cypress/results/output.json --reportDir ../../../target/kibana-osquery/cypress/results && yarn junit:transform && mkdir -p ../../../target/junit && cp ../../../target/kibana-osquery/cypress/results/*.xml ../../../target/junit/", "junit:transform": "node ../security_solution/scripts/junit_transformer --pathPattern '../../../target/kibana-osquery/cypress/results/*.xml' --rootDirectory ../../../ --reportName 'Osquery Cypress' --writeInPlace", diff --git a/x-pack/plugins/osquery/public/action_results/action_results_summary.tsx b/x-pack/plugins/osquery/public/action_results/action_results_summary.tsx index 9bdd9bc5a4528..6b9581249a075 100644 --- a/x-pack/plugins/osquery/public/action_results/action_results_summary.tsx +++ b/x-pack/plugins/osquery/public/action_results/action_results_summary.tsx @@ -16,6 +16,7 @@ import { useActionResultsPrivileges } from './use_action_privileges'; interface ActionResultsSummaryProps { actionId: string; + startDate?: string; expirationDate?: string; agentIds?: string[]; error?: string; @@ -32,6 +33,7 @@ const ActionResultsSummaryComponent: React.FC = ({ expirationDate, agentIds, error, + startDate, }) => { const [pageIndex] = useState(0); const [pageSize] = useState(50); @@ -46,6 +48,7 @@ const ActionResultsSummaryComponent: React.FC = ({ data: { aggregations, edges }, } = useActionResults({ actionId, + startDate, activePage: pageIndex, agentIds, limit: pageSize, @@ -158,7 +161,7 @@ const ActionResultsSummaryComponent: React.FC = ({ setIsLive(() => { if (!agentIds?.length || expired || error) return false; - return !!(aggregations.totalResponded !== agentIds?.length); + return aggregations.totalResponded !== agentIds?.length; }); }, [agentIds?.length, aggregations.totalResponded, error, expired]); diff --git a/x-pack/plugins/osquery/public/action_results/use_action_results.ts b/x-pack/plugins/osquery/public/action_results/use_action_results.ts index ef7dbad151d20..8c20e4ed1c602 100644 --- a/x-pack/plugins/osquery/public/action_results/use_action_results.ts +++ b/x-pack/plugins/osquery/public/action_results/use_action_results.ts @@ -34,6 +34,7 @@ export interface ResultsArgs { export interface UseActionResults { actionId: string; activePage: number; + startDate?: string; agentIds?: string[]; direction: Direction; limit: number; @@ -51,6 +52,7 @@ export const useActionResults = ({ limit, sortField, kuery, + startDate, skip = false, isLive = false, }: UseActionResults) => { @@ -64,6 +66,7 @@ export const useActionResults = ({ data.search.search( { actionId, + startDate, factoryQueryType: OsqueryQueries.actionResults, kuery, pagination: generateTablePaginationOptions(activePage, limit), diff --git a/x-pack/plugins/osquery/public/agents/agent_grouper.ts b/x-pack/plugins/osquery/public/agents/agent_grouper.ts index 156f09b5c130b..1375c30437d60 100644 --- a/x-pack/plugins/osquery/public/agents/agent_grouper.ts +++ b/x-pack/plugins/osquery/public/agents/agent_grouper.ts @@ -32,6 +32,7 @@ export const generateAgentOption = ( ) => ({ label, options: data.map((agent) => ({ + disabled: agent.status !== 'online', label: `${agent.local_metadata.host.hostname} (${agent.local_metadata.elastic.agent.id})`, key: agent.local_metadata.elastic.agent.id, color: getColor(groupType), diff --git a/x-pack/plugins/osquery/public/agents/agents_table.tsx b/x-pack/plugins/osquery/public/agents/agents_table.tsx index 6bf041bf9d9d0..f6b80e670f95b 100644 --- a/x-pack/plugins/osquery/public/agents/agents_table.tsx +++ b/x-pack/plugins/osquery/public/agents/agents_table.tsx @@ -22,7 +22,7 @@ import useDebounce from 'react-use/lib/useDebounce'; import { FormattedMessage } from '@kbn/i18n-react'; import { useKibana } from '../common/lib/kibana'; import { useAllAgents } from './use_all_agents'; -import { useAgentGroups } from './use_agent_groups'; + import { AgentGrouper } from './agent_grouper'; import { getNumAgentsInGrouping, @@ -68,15 +68,9 @@ const AgentsTableComponent: React.FC = ({ agentSelection, onCh [searchValue] ); - // grouping related - const { - isLoading: groupsLoading, - data: agentGroupsData, - isFetched: groupsFetched, - } = useAgentGroups(); const { isLoading: agentsLoading, - data: agents, + data: agentList, isFetched: agentsFetched, } = useAllAgents(debouncedSearchValue, { perPage, @@ -101,7 +95,7 @@ const AgentsTableComponent: React.FC = ({ agentSelection, onCh selectedGroups: SelectedGroups; } = generateAgentSelection(selection); if (newAgentSelection.allAgentsSelected) { - setNumAgentsSelected(agentGroupsData?.total ?? 0); + setNumAgentsSelected(agentList?.total ?? 0); } else { const checkAgent = generateAgentCheck(selectedGroups); setNumAgentsSelected( @@ -110,14 +104,14 @@ const AgentsTableComponent: React.FC = ({ agentSelection, onCh // add the number of agents added via policy and platform groups getNumAgentsInGrouping(selectedGroups) - // subtract the number of agents double counted by policy/platform selections - getNumOverlapped(selectedGroups, agentGroupsData?.groups?.overlap ?? {}) + getNumOverlapped(selectedGroups, agentList?.groups?.overlap ?? {}) ); } onChange(newAgentSelection); setSelectedOptions(selection); }, - [agentGroupsData, onChange] + [agentList?.groups?.overlap, agentList?.total, onChange] ); useEffect(() => { @@ -159,24 +153,23 @@ const AgentsTableComponent: React.FC = ({ agentSelection, onCh }, [agentSelection, onSelection, options, selectedOptions]); useEffect(() => { - if (agentsFetched && groupsFetched && agentGroupsData) { + if (agentsFetched && agentList?.groups) { // Cap policies to 10 on init dropdown - const policies = (agentGroupsData?.groups.policies || []).slice( + const policies = (agentList.groups?.policies || []).slice( 0, searchValue === '' ? 10 : undefined ); const grouper = new AgentGrouper(); // update the groups when groups or agents have changed - grouper.setTotalAgents(agentGroupsData?.total); - grouper.updateGroup(AGENT_GROUP_KEY.Platform, agentGroupsData?.groups.platforms); + grouper.setTotalAgents(agentList.total); + grouper.updateGroup(AGENT_GROUP_KEY.Platform, agentList?.groups?.platforms ?? []); grouper.updateGroup(AGENT_GROUP_KEY.Policy, policies); - // @ts-expect-error update types - grouper.updateGroup(AGENT_GROUP_KEY.Agent, agents); + grouper.updateGroup(AGENT_GROUP_KEY.Agent, agentList?.agents); const newOptions = grouper.generateOptions(); setOptions((prevOptions) => (!deepEqual(prevOptions, newOptions) ? newOptions : prevOptions)); } - }, [groupsLoading, agents, agentsFetched, groupsFetched, agentGroupsData, searchValue]); + }, [agentList?.agents, agentList?.groups, agentList?.total, agentsFetched, searchValue]); const renderOption = useCallback((option, searchVal, contentClassName) => { const { label, value } = option; @@ -201,10 +194,9 @@ const AgentsTableComponent: React.FC = ({ agentSelection, onCh setModifyingSearch(v !== ''); setSearchValue(v); }, []); - const isFetched = groupsFetched && agentsFetched && agentGroupsData; const renderNoAgentAvailableWarning = () => { - if (isFetched && !options.length) { + if (agentsFetched && agentList?.groups && !options.length) { return ( <> @@ -243,7 +235,7 @@ const AgentsTableComponent: React.FC = ({ agentSelection, onCh { it('should handle empty input', () => { diff --git a/x-pack/plugins/osquery/public/agents/helpers.ts b/x-pack/plugins/osquery/public/agents/helpers.ts index 62ad37de506cb..b84c6e4957286 100644 --- a/x-pack/plugins/osquery/public/agents/helpers.ts +++ b/x-pack/plugins/osquery/public/agents/helpers.ts @@ -5,17 +5,14 @@ * 2.0. */ -import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { euiPaletteColorBlindBehindText } from '@elastic/eui'; import type { - SelectedGroups, - Overlap, - Group, AgentOptionValue, - AggregationDataPoint, AgentSelection, - GroupOptionValue, GroupOption, + GroupOptionValue, + Overlap, + SelectedGroups, } from './types'; import { AGENT_GROUP_KEY } from './types'; @@ -34,49 +31,6 @@ export const getNumOverlapped = ( return sum; }; -interface Aggs extends estypes.AggregationsTermsAggregateBase { - buckets: AggregationDataPoint[]; -} - -export const processAggregations = ( - aggs: Record | undefined -) => { - if (!aggs) { - return { - platforms: [], - overlap: {}, - policies: [], - }; - } - - const platforms: Group[] = []; - const overlap: Overlap = {}; - const platformTerms = aggs.platforms as Aggs; - const policyTerms = aggs.policies as Aggs; - - const policies = - policyTerms?.buckets.map((o) => ({ name: o.key, id: o.key, size: o.doc_count })) ?? []; - - if (platformTerms?.buckets) { - for (const { key, doc_count: size, policies: platformPolicies } of platformTerms.buckets) { - platforms.push({ name: key, id: key, size }); - if (platformPolicies?.buckets && policies.length > 0) { - overlap[key] = platformPolicies.buckets.reduce((acc: { [key: string]: number }, pol) => { - acc[pol.key] = pol.doc_count; - - return acc; - }, {} as { [key: string]: number }); - } - } - } - - return { - platforms, - overlap, - policies, - }; -}; - export const generateColorPicker = () => { const visColorsBehindText = euiPaletteColorBlindBehindText(); const typeColors = new Map(); diff --git a/x-pack/plugins/osquery/public/agents/types.ts b/x-pack/plugins/osquery/public/agents/types.ts index 71ebdc2983aef..6f443641b227b 100644 --- a/x-pack/plugins/osquery/public/agents/types.ts +++ b/x-pack/plugins/osquery/public/agents/types.ts @@ -5,23 +5,9 @@ * 2.0. */ -import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import type { EuiComboBoxOptionOption } from '@elastic/eui'; import type { Agent } from '../../common/shared_imports'; -interface BaseDataPoint { - key: string; - doc_count: number; -} - -interface AggDataPoint extends estypes.AggregationsTermsAggregateBase { - buckets: AggregationDataPoint[]; -} - -export type AggregationDataPoint = BaseDataPoint & { - [key: string]: AggDataPoint; -}; - export interface Group { id: string; name: string; diff --git a/x-pack/plugins/osquery/public/agents/use_agent_groups.ts b/x-pack/plugins/osquery/public/agents/use_agent_groups.ts deleted file mode 100644 index c7b72b489bbec..0000000000000 --- a/x-pack/plugins/osquery/public/agents/use_agent_groups.ts +++ /dev/null @@ -1,109 +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 { useQuery } from '@tanstack/react-query'; -import { i18n } from '@kbn/i18n'; -import { lastValueFrom } from 'rxjs'; -import { useKibana } from '../common/lib/kibana'; -import { useAgentPolicies } from './use_agent_policies'; - -import type { AgentsRequestOptions, AgentsStrategyResponse } from '../../common/search_strategy'; -import { OsqueryQueries } from '../../common/search_strategy'; - -import { processAggregations } from './helpers'; -import { generateTablePaginationOptions } from '../common/helpers'; -import { useErrorToast } from '../common/hooks/use_error_toast'; -import { useOsqueryPolicies } from './use_osquery_policies'; - -export const useAgentGroups = () => { - const { data } = useKibana().services; - const setErrorToast = useErrorToast(); - - const { data: osqueryPolicies, isFetched: isOsqueryPoliciesFetched } = useOsqueryPolicies(); - const { agentPoliciesLoading, agentPolicyById } = useAgentPolicies(osqueryPolicies); - - return useQuery< - AgentsStrategyResponse, - unknown, - { - total: number; - groups: ReturnType; - } - >( - ['agentGroups'], - async () => { - const policiesQuery = osqueryPolicies?.reduce((acc, policy) => `${acc} OR ${policy}`); - - const responseData = await lastValueFrom( - data.search.search( - { - kuery: `policy_id: ( ${policiesQuery} )`, - factoryQueryType: OsqueryQueries.agents, - pagination: generateTablePaginationOptions(0, 9000), - sort: { - direction: 'asc', - field: 'local_metadata.os.platform', - }, - } as AgentsRequestOptions, - { - strategy: 'osquerySearchStrategy', - } - ) - ); - - return responseData; - }, - { - select: (response) => { - const { platforms, overlap, policies } = processAggregations( - response.rawResponse.aggregations - ); - - return { - total: response.total ?? 0, - groups: { - platforms, - overlap, - policies: policies.map((p) => { - const name = agentPolicyById[p.id]?.name ?? p.name; - - return { - ...p, - name, - }; - }), - }, - }; - }, - placeholderData: { - total: 0, - edges: [], - rawResponse: { - took: 0, - timed_out: false, - _shards: { - failed: 0, - successful: 0, - total: 0, - }, - hits: { - hits: [], - }, - }, - }, - refetchOnWindowFocus: false, - keepPreviousData: true, - enabled: isOsqueryPoliciesFetched && !agentPoliciesLoading, - onSuccess: () => setErrorToast(), - onError: (error) => - setErrorToast(error as Error, { - title: i18n.translate('xpack.osquery.agent_groups.fetchError', { - defaultMessage: 'Error while fetching agent groups', - }), - }), - } - ); -}; diff --git a/x-pack/plugins/osquery/public/agents/use_agent_policies.ts b/x-pack/plugins/osquery/public/agents/use_agent_policies.ts deleted file mode 100644 index 235789ef548a3..0000000000000 --- a/x-pack/plugins/osquery/public/agents/use_agent_policies.ts +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { mapKeys } from 'lodash'; -import type { UseQueryResult } from '@tanstack/react-query'; -import { useQueries } from '@tanstack/react-query'; -import { i18n } from '@kbn/i18n'; -import type { GetOneAgentPolicyResponse } from '@kbn/fleet-plugin/common'; -import { API_VERSIONS } from '../../common/constants'; -import { useKibana } from '../common/lib/kibana'; -import { useErrorToast } from '../common/hooks/use_error_toast'; - -export const useAgentPolicies = (policyIds: string[] = []) => { - const { http } = useKibana().services; - const setErrorToast = useErrorToast(); - - const agentResponse = useQueries({ - queries: policyIds.map((policyId) => ({ - queryKey: ['agentPolicy', policyId], - queryFn: () => - http.get(`/internal/osquery/fleet_wrapper/agent_policies/${policyId}`, { - version: API_VERSIONS.internal.v1, - }), - enabled: policyIds.length > 0, - onSuccess: () => setErrorToast(), - - onError: (error: Error) => - setErrorToast(error, { - title: i18n.translate('xpack.osquery.action_policy_details.fetchError', { - defaultMessage: 'Error while fetching policy details', - }), - }), - })), - }) as Array>; - - const agentPoliciesLoading = agentResponse.some((p) => p.isLoading); - const agentPolicies = agentResponse.map((p) => p.data?.item); - const agentPolicyById = mapKeys(agentPolicies, 'id'); - - return { agentPoliciesLoading, agentPolicies, agentPolicyById }; -}; diff --git a/x-pack/plugins/osquery/public/agents/use_all_agents.ts b/x-pack/plugins/osquery/public/agents/use_all_agents.ts index 98985b1c38505..d0ea65c6bab05 100644 --- a/x-pack/plugins/osquery/public/agents/use_all_agents.ts +++ b/x-pack/plugins/osquery/public/agents/use_all_agents.ts @@ -8,7 +8,8 @@ import { i18n } from '@kbn/i18n'; import { useQuery } from '@tanstack/react-query'; -import type { ListResult, Agent } from '@kbn/fleet-plugin/common'; +import type { Agent } from '@kbn/fleet-plugin/common'; +import type { processAggregations } from '../../common/utils/aggregations'; import { API_VERSIONS } from '../../common/constants'; import { useErrorToast } from '../common/hooks/use_error_toast'; import { useKibana } from '../common/lib/kibana'; @@ -27,7 +28,11 @@ export const useAllAgents = (searchValue = '', opts: RequestOptions = { perPage: const { data: osqueryPolicies, isFetched } = useOsqueryPolicies(); - return useQuery, 'items'> & { agents: Agent[] }, unknown, Agent[]>( + return useQuery<{ + agents: Agent[]; + groups: ReturnType; + total: number; + }>( ['agents', osqueryPolicies, searchValue, perPage], () => { let kuery = ''; @@ -37,6 +42,8 @@ export const useAllAgents = (searchValue = '', opts: RequestOptions = { perPage: if (searchValue) { kuery += ` and (local_metadata.host.hostname:*${searchValue}* or local_metadata.elastic.agent.id:*${searchValue}*)`; + } else { + kuery += ` and (status:online)`; } } @@ -49,7 +56,6 @@ export const useAllAgents = (searchValue = '', opts: RequestOptions = { perPage: }); }, { - select: (data) => data?.agents || [], enabled: isFetched && !!osqueryPolicies?.length, onSuccess: () => setErrorToast(), onError: (error) => diff --git a/x-pack/plugins/osquery/public/form/index.ts b/x-pack/plugins/osquery/public/form/index.ts index 623477aaa0d16..1da4865905166 100644 --- a/x-pack/plugins/osquery/public/form/index.ts +++ b/x-pack/plugins/osquery/public/form/index.ts @@ -10,3 +10,4 @@ export { QueryDescriptionField } from './query_description_field'; export { IntervalField } from './interval_field'; export { QueryIdField } from './query_id_field'; export { ResultsTypeField } from './results_type_field'; +export { TimeoutField } from './timeout_field'; diff --git a/x-pack/plugins/osquery/public/form/timeout_field.tsx b/x-pack/plugins/osquery/public/form/timeout_field.tsx new file mode 100644 index 0000000000000..a9ad26d11e173 --- /dev/null +++ b/x-pack/plugins/osquery/public/form/timeout_field.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 React, { useCallback, useMemo } from 'react'; +import deepEqual from 'fast-deep-equal'; +import { useController } from 'react-hook-form'; +import type { EuiFieldNumberProps } from '@elastic/eui'; +import { + EuiFieldNumber, + EuiFlexGroup, + EuiFlexItem, + EuiFormRow, + EuiIconTip, + EuiText, +} from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +import { FormattedMessage } from '@kbn/i18n-react'; + +import { QUERY_TIMEOUT } from '../../common/constants'; + +const timeoutFieldValidations = { + min: { + message: i18n.translate('xpack.osquery.pack.queryFlyoutForm.timeoutFieldMinNumberError', { + defaultMessage: 'Timeout value must be greater than {than} seconds.', + values: { than: QUERY_TIMEOUT.DEFAULT }, + }), + value: QUERY_TIMEOUT.DEFAULT, + }, + max: { + message: i18n.translate('xpack.osquery.pack.queryFlyoutForm.timeoutFieldMaxNumberError', { + defaultMessage: 'Timeout value must be lower than {than} seconds.', + values: { than: QUERY_TIMEOUT.MAX }, + }), + value: QUERY_TIMEOUT.MAX, + }, +}; + +interface TimeoutFieldProps { + euiFieldProps?: Record; +} + +const TimeoutFieldComponent = ({ euiFieldProps }: TimeoutFieldProps) => { + const { + field: { onChange, value }, + fieldState: { error }, + } = useController({ + name: 'timeout', + defaultValue: QUERY_TIMEOUT.DEFAULT, + rules: { + ...timeoutFieldValidations, + }, + }); + const handleChange = useCallback( + (e: React.ChangeEvent) => { + const numberValue = e.target.valueAsNumber ? e.target.valueAsNumber : 0; + onChange(numberValue); + }, + [onChange] + ); + const hasError = useMemo(() => !!error?.message, [error?.message]); + + return ( + + + + + + + + + } + fullWidth + error={error?.message} + isInvalid={hasError} + labelAppend={ + + + + + + } + > + + + ); +}; + +export const TimeoutField = React.memo(TimeoutFieldComponent, deepEqual); diff --git a/x-pack/plugins/osquery/public/live_queries/form/index.tsx b/x-pack/plugins/osquery/public/live_queries/form/index.tsx index 5f256b505043f..287c8b25b45b1 100644 --- a/x-pack/plugins/osquery/public/live_queries/form/index.tsx +++ b/x-pack/plugins/osquery/public/live_queries/form/index.tsx @@ -10,7 +10,7 @@ import { FormattedMessage } from '@kbn/i18n-react'; import type { ECSMapping } from '@kbn/osquery-io-ts-types'; import React, { useCallback, useContext, useEffect, useMemo, useState } from 'react'; import { useForm as useHookForm, FormProvider } from 'react-hook-form'; -import { isEmpty, find, pickBy } from 'lodash'; +import { isEmpty, find, pickBy, isNumber } from 'lodash'; import { containsDynamicQuery, @@ -39,6 +39,7 @@ export interface LiveQueryFormFields { savedQueryId?: string | null; ecs_mapping: ECSMapping; packId: string[]; + timeout?: number; queryType: 'query' | 'pack'; } @@ -151,10 +152,10 @@ const LiveQueryFormComponent: React.FC = ({ alert_ids: values.alertIds, pack_id: queryType === 'pack' && values?.packId?.length ? values?.packId[0] : undefined, ecs_mapping: values.ecs_mapping, + timeout: values.timeout, }, - (value) => !isEmpty(value) + (value) => !isEmpty(value) || isNumber(value) ) as unknown as LiveQueryFormFields; - await mutateAsync(serializedData); }, [alertAttachmentContext, mutateAsync, queryType] @@ -221,6 +222,7 @@ const LiveQueryFormComponent: React.FC = ({ singleQueryDetails?.action_id ? ( = ({ singleQueryDetails?.action_id, singleQueryDetails?.expiration, singleQueryDetails?.agents, + liveQueryDetails, serializedData.ecs_mapping, liveQueryActionId, ] diff --git a/x-pack/plugins/osquery/public/live_queries/form/live_query_query_field.tsx b/x-pack/plugins/osquery/public/live_queries/form/live_query_query_field.tsx index 100319f7c16a5..23ef0524dbb15 100644 --- a/x-pack/plugins/osquery/public/live_queries/form/live_query_query_field.tsx +++ b/x-pack/plugins/osquery/public/live_queries/form/live_query_query_field.tsx @@ -11,6 +11,8 @@ import { EuiCodeBlock, EuiFormRow, EuiAccordion, EuiSpacer } from '@elastic/eui' import React, { useCallback, useMemo, useState } from 'react'; import { useController, useFormContext } from 'react-hook-form'; import { i18n } from '@kbn/i18n'; +import { QUERY_TIMEOUT } from '../../../common/constants'; +import { TimeoutField } from '../../form/timeout_field'; import type { LiveQueryFormFields } from '.'; import { OsqueryEditor } from '../../editor'; import { useKibana } from '../../common/lib/kibana'; @@ -68,6 +70,7 @@ const LiveQueryQueryFieldComponent: React.FC = ({ resetField('query', { defaultValue: savedQuery.query }); resetField('savedQueryId', { defaultValue: savedQuery.savedQueryId }); resetField('ecs_mapping', { defaultValue: savedQuery.ecs_mapping ?? {} }); + resetField('timeout', { defaultValue: savedQuery.timeout ?? QUERY_TIMEOUT.DEFAULT }); if (!isEmpty(savedQuery.ecs_mapping)) { setAdvancedContentState('open'); @@ -122,6 +125,7 @@ const LiveQueryQueryFieldComponent: React.FC = ({ {!isSavedQueryDisabled && ( )} + = ({ data-test-subj="advanced-accordion-content" > + + )} diff --git a/x-pack/plugins/osquery/public/packs/form/queries_field.tsx b/x-pack/plugins/osquery/public/packs/form/queries_field.tsx index d40532bf80814..3e62a5639e1f7 100644 --- a/x-pack/plugins/osquery/public/packs/form/queries_field.tsx +++ b/x-pack/plugins/osquery/public/packs/form/queries_field.tsx @@ -14,6 +14,7 @@ import { FormattedMessage } from '@kbn/i18n-react'; import deepEqual from 'fast-deep-equal'; import { useController, useFormContext, useWatch, useFieldArray } from 'react-hook-form'; +import { QUERY_TIMEOUT } from '../../../common/constants'; import { PackQueriesTable } from '../pack_queries_table'; import { QueryFlyout } from '../queries/query_flyout'; import { OsqueryPackUploader } from './pack_uploader'; @@ -84,6 +85,7 @@ const QueriesFieldComponent: React.FC = ({ euiFieldProps }) = draft.id = updatedQuery.id; draft.interval = updatedQuery.interval; draft.query = updatedQuery.query; + draft.timeout = updatedQuery.timeout; if (updatedQuery.platform?.length) { draft.platform = updatedQuery.platform; @@ -137,6 +139,7 @@ const QueriesFieldComponent: React.FC = ({ euiFieldProps }) = { id: newQueryId, interval: newQuery.interval ?? parsedContent.interval ?? '3600', + timeout: newQuery.timeout ?? parsedContent.timeout ?? QUERY_TIMEOUT.DEFAULT, query: newQuery.query, version: newQuery.version ?? parsedContent.version, snapshot: newQuery.snapshot ?? parsedContent.snapshot, diff --git a/x-pack/plugins/osquery/public/packs/form/utils.ts b/x-pack/plugins/osquery/public/packs/form/utils.ts index e04db1ed5b237..c44fb468bb80d 100644 --- a/x-pack/plugins/osquery/public/packs/form/utils.ts +++ b/x-pack/plugins/osquery/public/packs/form/utils.ts @@ -17,6 +17,7 @@ export const convertPackQueriesToSO = (queries: Record = ({ }); resetField('version', { defaultValue: savedQuery.version ? [savedQuery.version] : [] }); resetField('interval', { defaultValue: savedQuery.interval ? savedQuery.interval : 3600 }); + resetField('timeout', { + defaultValue: savedQuery.timeout ? savedQuery.timeout : QUERY_TIMEOUT.DEFAULT, + }); resetField('snapshot', { defaultValue: savedQuery.snapshot ?? true }); resetField('removed', { defaultValue: savedQuery.removed }); resetField('ecs_mapping', { defaultValue: savedQuery.ecs_mapping ?? {} }); @@ -146,9 +155,14 @@ const QueryFlyoutComponent: React.FC = ({ - - - + + + + + + + + diff --git a/x-pack/plugins/osquery/public/packs/queries/use_pack_query_form.tsx b/x-pack/plugins/osquery/public/packs/queries/use_pack_query_form.tsx index 1a0ecdbe71c59..ea6f2a2105b41 100644 --- a/x-pack/plugins/osquery/public/packs/queries/use_pack_query_form.tsx +++ b/x-pack/plugins/osquery/public/packs/queries/use_pack_query_form.tsx @@ -11,6 +11,7 @@ import type { Draft } from 'immer'; import { produce } from 'immer'; import { useMemo } from 'react'; import type { ECSMapping } from '@kbn/osquery-io-ts-types'; +import { QUERY_TIMEOUT } from '../../../common/constants'; import type { Shard } from '../../../common/utils/converters'; export interface UsePackQueryFormProps { @@ -22,6 +23,7 @@ export interface PackSOQueryFormData { id: string; query: string; interval: string; + timeout?: number; snapshot?: boolean; removed?: boolean; platform?: string | undefined; @@ -37,6 +39,7 @@ export interface PackQueryFormData { description?: string; query: string; interval: number; + timeout?: number; snapshot?: boolean; removed?: boolean; platform?: string | undefined; @@ -48,6 +51,7 @@ const deserializer = (payload: PackSOQueryFormData): PackQueryFormData => ({ id: payload.id, query: payload.query, interval: payload.interval ? parseInt(payload.interval, 10) : 3600, + timeout: payload.timeout || QUERY_TIMEOUT.DEFAULT, snapshot: payload.snapshot, removed: payload.removed, platform: payload.platform, diff --git a/x-pack/plugins/osquery/public/results/results_table.tsx b/x-pack/plugins/osquery/public/results/results_table.tsx index c74ca9d607dc1..48a3e7f355a18 100644 --- a/x-pack/plugins/osquery/public/results/results_table.tsx +++ b/x-pack/plugins/osquery/public/results/results_table.tsx @@ -92,6 +92,7 @@ const ResultsTableComponent: React.FC = ({ data: { aggregations }, } = useActionResults({ actionId, + startDate, activePage: 0, agentIds, limit: 0, @@ -140,6 +141,7 @@ const ResultsTableComponent: React.FC = ({ const { data: allResultsData, isLoading } = useAllResults({ actionId, + startDate, activePage: pagination.pageIndex, limit: pagination.pageSize, isLive, diff --git a/x-pack/plugins/osquery/public/results/use_all_results.ts b/x-pack/plugins/osquery/public/results/use_all_results.ts index 09f18cfd2d17c..8dca0d1ba4a87 100644 --- a/x-pack/plugins/osquery/public/results/use_all_results.ts +++ b/x-pack/plugins/osquery/public/results/use_all_results.ts @@ -33,6 +33,7 @@ export interface ResultsArgs { interface UseAllResults { actionId: string; activePage: number; + startDate?: string; limit: number; sort: Array<{ field: string; direction: Direction }>; kuery?: string; @@ -43,6 +44,7 @@ interface UseAllResults { export const useAllResults = ({ actionId, activePage, + startDate, limit, sort, kuery, @@ -59,6 +61,7 @@ export const useAllResults = ({ data.search.search( { actionId, + startDate, factoryQueryType: OsqueryQueries.results, kuery, pagination: generateTablePaginationOptions(activePage, limit), diff --git a/x-pack/plugins/osquery/public/routes/saved_queries/edit/tabs.tsx b/x-pack/plugins/osquery/public/routes/saved_queries/edit/tabs.tsx index e73dc404370cb..c55bebcd9056b 100644 --- a/x-pack/plugins/osquery/public/routes/saved_queries/edit/tabs.tsx +++ b/x-pack/plugins/osquery/public/routes/saved_queries/edit/tabs.tsx @@ -63,6 +63,7 @@ const ResultTabsComponent: React.FC = ({ 'data-test-subj': 'osquery-status-tab', content: ( = ({ + + + + + + + + {!viewMode && hasPlayground && ( diff --git a/x-pack/plugins/osquery/public/saved_queries/form/use_saved_query_form.tsx b/x-pack/plugins/osquery/public/saved_queries/form/use_saved_query_form.tsx index 453fb9b87c6cd..340541eb5d598 100644 --- a/x-pack/plugins/osquery/public/saved_queries/form/use_saved_query_form.tsx +++ b/x-pack/plugins/osquery/public/saved_queries/form/use_saved_query_form.tsx @@ -11,6 +11,7 @@ import type { Draft } from 'immer'; import produce from 'immer'; import { useMemo } from 'react'; import type { ECSMapping } from '@kbn/osquery-io-ts-types'; +import { QUERY_TIMEOUT } from '../../../common/constants'; import { useSavedQueries } from '../use_saved_queries'; export interface SavedQuerySOFormData { @@ -18,6 +19,7 @@ export interface SavedQuerySOFormData { description?: string; query?: string; interval?: string; + timeout?: number; snapshot?: boolean; removed?: boolean; platform?: string; @@ -30,6 +32,7 @@ export interface SavedQueryFormData { description?: string; query?: string; interval?: number; + timeout?: number; snapshot?: boolean; removed?: boolean; platform?: string; @@ -46,6 +49,7 @@ const deserializer = (payload: SavedQuerySOFormData): SavedQueryFormData => ({ description: payload.description, query: payload.query, interval: payload.interval ? parseInt(payload.interval, 10) : 3600, + timeout: payload.timeout ?? QUERY_TIMEOUT.DEFAULT, snapshot: payload.snapshot ?? true, removed: payload.removed ?? false, platform: payload.platform, @@ -95,6 +99,7 @@ export const useSavedQueryForm = ({ defaultValue }: UseSavedQueryFormProps) => { id: '', query: '', interval: 3600, + timeout: QUERY_TIMEOUT.DEFAULT, ecs_mapping: {}, snapshot: true, }, diff --git a/x-pack/plugins/osquery/public/saved_queries/saved_queries_dropdown.tsx b/x-pack/plugins/osquery/public/saved_queries/saved_queries_dropdown.tsx index 411813c655e24..690341fd2221f 100644 --- a/x-pack/plugins/osquery/public/saved_queries/saved_queries_dropdown.tsx +++ b/x-pack/plugins/osquery/public/saved_queries/saved_queries_dropdown.tsx @@ -25,7 +25,7 @@ export interface SavedQueriesDropdownProps { disabled?: boolean; onChange: ( value: - | (Pick & { + | (Pick & { savedQueryId: string; }) | null diff --git a/x-pack/plugins/osquery/public/shared_components/osquery_response_action_type/index.tsx b/x-pack/plugins/osquery/public/shared_components/osquery_response_action_type/index.tsx index 064e55d9350b2..cba12d5ef3e6e 100644 --- a/x-pack/plugins/osquery/public/shared_components/osquery_response_action_type/index.tsx +++ b/x-pack/plugins/osquery/public/shared_components/osquery_response_action_type/index.tsx @@ -24,23 +24,27 @@ interface OsqueryResponseActionsValues { id?: string; ecsMapping?: ECSMapping; query?: string; + timeout: number; packId?: string; queries?: Array<{ id: string; ecs_mapping: ECSMapping; query: string; + timeout?: number; }>; } interface OsqueryResponseActionsParamsFormFields { savedQueryId: string | null; ecs_mapping: ECSMapping; + timeout: number; query: string; packId?: string[]; queries: Array<{ id: string; ecs_mapping: ECSMapping; query: string; + timeout?: number; }>; queryType: 'query' | 'pack'; } @@ -115,6 +119,7 @@ const OsqueryResponseActionParamsFormComponent = ({ : { savedQueryId: formData.savedQueryId, query: formData.query, + timeout: formData.timeout, ecsMapping: formData.ecs_mapping, } ); diff --git a/x-pack/plugins/osquery/server/common/types.ts b/x-pack/plugins/osquery/server/common/types.ts index 999041c0debcf..364d4d95328c7 100644 --- a/x-pack/plugins/osquery/server/common/types.ts +++ b/x-pack/plugins/osquery/server/common/types.ts @@ -21,6 +21,7 @@ export interface PackSavedObject { name: string; query: string; interval: number; + timeout?: number; snapshot?: boolean; removed?: boolean; ecs_mapping?: Record; @@ -41,6 +42,7 @@ export interface SavedQuerySavedObject { description: string | undefined; query: string; interval: number | string; + timeout?: number; snapshot?: boolean; removed?: boolean; platform: string; diff --git a/x-pack/plugins/osquery/server/handlers/action/create_action_handler.ts b/x-pack/plugins/osquery/server/handlers/action/create_action_handler.ts index d60c7bae8d9b3..79e0cdb2d2a48 100644 --- a/x-pack/plugins/osquery/server/handlers/action/create_action_handler.ts +++ b/x-pack/plugins/osquery/server/handlers/action/create_action_handler.ts @@ -7,7 +7,7 @@ import { v4 as uuidv4 } from 'uuid'; import moment from 'moment'; -import { filter, isEmpty, map, omit, pick, pickBy, some } from 'lodash'; +import { filter, isEmpty, isNumber, map, omit, pick, pickBy, some } from 'lodash'; import type { SavedObjectsClientContract } from '@kbn/core/server'; import type { ParsedTechnicalFields } from '@kbn/rule-registry-plugin/common'; import type { CreateLiveQueryRequestBodySchema } from '../../../common/api'; @@ -17,7 +17,7 @@ import { parseAgentSelection } from '../../lib/parse_agent_groups'; import { packSavedObjectType } from '../../../common/types'; import type { OsqueryAppContext } from '../../lib/osquery_app_context_services'; import { convertSOQueriesToPack } from '../../routes/pack/utils'; -import { ACTIONS_INDEX } from '../../../common/constants'; +import { ACTIONS_INDEX, QUERY_TIMEOUT } from '../../../common/constants'; import { TELEMETRY_EBT_LIVE_QUERY_EVENT } from '../../lib/telemetry/constants'; import type { PackSavedObject } from '../../common/types'; import { CustomHttpRequestError } from '../../common/error'; @@ -100,9 +100,10 @@ export const createActionHandler = async ( ecs_mapping: packQuery.ecs_mapping, version: packQuery.version, platform: packQuery.platform, + timeout: packQuery.timeout, agents: selectedAgents, }, - (value) => !isEmpty(value) + (value) => !isEmpty(value) || isNumber(value) ); }) : await createDynamicQueries({ @@ -125,6 +126,7 @@ export const createActionHandler = async ( input_type: 'osquery', agents: query.agents, user_id: metadata?.currentUser, + ...(query.timeout !== QUERY_TIMEOUT.DEFAULT ? { timeout: query.timeout } : {}), data: pick(query, ['id', 'query', 'ecs_mapping', 'version', 'platform']), }) ) diff --git a/x-pack/plugins/osquery/server/handlers/action/create_queries.ts b/x-pack/plugins/osquery/server/handlers/action/create_queries.ts index 78092859a3990..cf7f2563b3fbb 100644 --- a/x-pack/plugins/osquery/server/handlers/action/create_queries.ts +++ b/x-pack/plugins/osquery/server/handlers/action/create_queries.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { isEmpty, map, pickBy } from 'lodash'; +import { isEmpty, isNumber, map, pickBy } from 'lodash'; import { v4 as uuidv4 } from 'uuid'; import type { ParsedTechnicalFields } from '@kbn/rule-registry-plugin/common'; @@ -43,7 +43,7 @@ export const createDynamicQueries = async ({ alert_ids: params.alert_ids, agents, }, - (value) => !isEmpty(value) || value === true + (value) => !isEmpty(value) || value === true || isNumber(value) ); }) : [ @@ -61,10 +61,11 @@ export const createDynamicQueries = async ({ : undefined, ecs_mapping: params.ecs_mapping, alert_ids: params.alert_ids, + timeout: params.timeout, agents, ...(error ? { error } : {}), }, - (value) => !isEmpty(value) + (value) => !isEmpty(value) || isNumber(value) ), ]; diff --git a/x-pack/plugins/osquery/server/index.ts b/x-pack/plugins/osquery/server/index.ts index 4f2c732620df9..f82552cec52fb 100644 --- a/x-pack/plugins/osquery/server/index.ts +++ b/x-pack/plugins/osquery/server/index.ts @@ -6,7 +6,6 @@ */ import type { PluginConfigDescriptor, PluginInitializerContext } from '@kbn/core/server'; -import { OsqueryPlugin } from './plugin'; import type { ConfigType } from '../common/config'; import { ConfigSchema } from '../common/config'; @@ -16,7 +15,9 @@ export const config: PluginConfigDescriptor = { actionEnabled: true, }, }; -export function plugin(initializerContext: PluginInitializerContext) { +export async function plugin(initializerContext: PluginInitializerContext) { + const { OsqueryPlugin } = await import('./plugin'); + return new OsqueryPlugin(initializerContext); } diff --git a/x-pack/plugins/osquery/server/lib/parse_agent_groups.ts b/x-pack/plugins/osquery/server/lib/parse_agent_groups.ts index ab82b629f59ea..723216a675fb4 100644 --- a/x-pack/plugins/osquery/server/lib/parse_agent_groups.ts +++ b/x-pack/plugins/osquery/server/lib/parse_agent_groups.ts @@ -49,7 +49,7 @@ export const parseAgentSelection = async ( } = agentSelection; const agentService = context.service.getAgentService()?.asInternalUser; const packagePolicyService = context.service.getPackagePolicyService(); - const kueryFragments = []; + const kueryFragments = ['status:online']; if (agentService && packagePolicyService) { const osqueryPolicies = await aggregateResults(async (page, perPage) => { diff --git a/x-pack/plugins/osquery/server/lib/saved_query/saved_object_mappings.ts b/x-pack/plugins/osquery/server/lib/saved_query/saved_object_mappings.ts index 70bee246ae886..a28dc7bafae7f 100644 --- a/x-pack/plugins/osquery/server/lib/saved_query/saved_object_mappings.ts +++ b/x-pack/plugins/osquery/server/lib/saved_query/saved_object_mappings.ts @@ -8,6 +8,11 @@ import { produce } from 'immer'; import type { SavedObjectsType } from '@kbn/core/server'; import { SECURITY_SOLUTION_SAVED_OBJECT_INDEX } from '@kbn/core-saved-objects-server'; +import { + packAssetSavedObjectModelVersion1, + packSavedObjectModelVersion1, + savedQueryModelVersion1, +} from './saved_object_model_versions'; import { savedQuerySavedObjectType, packSavedObjectType, @@ -67,6 +72,9 @@ export const savedQuerySavedObjectMappings: SavedObjectsType['mappings'] = { interval: { type: 'keyword', }, + timeout: { + type: 'short', + }, ecs_mapping: { dynamic: false, properties: {}, @@ -80,6 +88,9 @@ export const savedQueryType: SavedObjectsType = { hidden: false, namespaceType: 'multiple-isolated', mappings: savedQuerySavedObjectMappings, + modelVersions: { + 1: savedQueryModelVersion1, + }, management: { importableAndExportable: true, getTitle: (savedObject) => savedObject.attributes.id, @@ -145,6 +156,9 @@ export const packSavedObjectMappings: SavedObjectsType['mappings'] = { interval: { type: 'text', }, + timeout: { + type: 'short', + }, platform: { type: 'keyword', }, @@ -166,6 +180,9 @@ export const packType: SavedObjectsType = { hidden: false, namespaceType: 'multiple-isolated', mappings: packSavedObjectMappings, + modelVersions: { + 1: packSavedObjectModelVersion1, + }, management: { defaultSearchField: 'name', importableAndExportable: true, @@ -219,6 +236,9 @@ export const packAssetSavedObjectMappings: SavedObjectsType['mappings'] = { interval: { type: 'text', }, + timeout: { + type: 'short', + }, platform: { type: 'keyword', }, @@ -242,6 +262,9 @@ export const packAssetType: SavedObjectsType = { importableAndExportable: true, visibleInManagement: false, }, + modelVersions: { + 1: packAssetSavedObjectModelVersion1, + }, namespaceType: 'agnostic', mappings: packAssetSavedObjectMappings, }; diff --git a/x-pack/plugins/osquery/server/lib/saved_query/saved_object_model_versions.ts b/x-pack/plugins/osquery/server/lib/saved_query/saved_object_model_versions.ts new file mode 100644 index 0000000000000..9ab021c7f0cfc --- /dev/null +++ b/x-pack/plugins/osquery/server/lib/saved_query/saved_object_model_versions.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 { SavedObjectsModelVersion } from '@kbn/core-saved-objects-server'; + +export const savedQueryModelVersion1: SavedObjectsModelVersion = { + changes: [ + { + type: 'mappings_addition', + addedMappings: { + timeout: { type: 'short' }, + }, + }, + ], +}; + +export const packSavedObjectModelVersion1: SavedObjectsModelVersion = { + changes: [ + { + type: 'mappings_addition', + addedMappings: { + queries: { + properties: { + timeout: { type: 'short' }, + }, + }, + }, + }, + ], +}; + +export const packAssetSavedObjectModelVersion1: SavedObjectsModelVersion = { + changes: [ + { + type: 'mappings_addition', + addedMappings: { + queries: { + properties: { + timeout: { type: 'short' }, + }, + }, + }, + }, + ], +}; diff --git a/x-pack/plugins/osquery/server/routes/fleet_wrapper/get_agents.ts b/x-pack/plugins/osquery/server/routes/fleet_wrapper/get_agents.ts index 44ce43305e697..c930bb4d9ffe5 100644 --- a/x-pack/plugins/osquery/server/routes/fleet_wrapper/get_agents.ts +++ b/x-pack/plugins/osquery/server/routes/fleet_wrapper/get_agents.ts @@ -6,10 +6,18 @@ */ import type { IRouter } from '@kbn/core/server'; +import type { ListWithKuery } from '@kbn/fleet-plugin/server/types'; +import { PACKAGE_POLICY_SAVED_OBJECT_TYPE } from '@kbn/fleet-plugin/common'; +import { filter, map, mapKeys, uniq } from 'lodash'; +import type { PackagePolicy } from '@kbn/fleet-plugin/server/types'; +import { satisfies } from 'semver'; +import type { SortResults } from '@elastic/elasticsearch/lib/api/types'; +import { processAggregations } from '../../../common/utils/aggregations'; +import { getInternalSavedObjectsClient } from '../utils'; import { getAgentsRequestQuerySchema } from '../../../common/api'; import type { GetAgentsRequestQuerySchema } from '../../../common/api'; import { buildRouteValidation } from '../../utils/build_validation/route_validation'; -import { API_VERSIONS } from '../../../common/constants'; +import { API_VERSIONS, OSQUERY_INTEGRATION_NAME } from '../../../common/constants'; import { PLUGIN_ID } from '../../../common'; import type { OsqueryAppContext } from '../../lib/osquery_app_context_services'; @@ -33,17 +41,89 @@ export const getAgentsRoute = (router: IRouter, osqueryContext: OsqueryAppContex }, }, async (context, request, response) => { - let agents; + let esAgents; + const query = request.query as ListWithKuery & { + showInactive: boolean; + searchAfter?: SortResults; + pitId?: string; + getStatusSummary?: boolean; + }; try { - agents = await osqueryContext.service - .getAgentService() - ?.asInternalUser // @ts-expect-error update types - .listAgents(request.query); + esAgents = await osqueryContext.service.getAgentService()?.asInternalUser.listAgents({ + page: query.page, + perPage: query.perPage, + sortField: query.sortField, + sortOrder: query.sortOrder, + showUpgradeable: query.showUpgradeable, + getStatusSummary: query.getStatusSummary, + pitId: query.pitId, + searchAfter: query.searchAfter, + kuery: query.kuery, + showInactive: query.showInactive, + aggregations: { + platforms: { + terms: { + field: 'local_metadata.os.platform', + }, + }, + policies: { + terms: { + field: 'policy_id', + size: 2000, + }, + }, + }, + }); } catch (error) { return response.badRequest({ body: error }); } - return response.ok({ body: agents }); + const internalSavedObjectsClient = await getInternalSavedObjectsClient( + osqueryContext.getStartServices + ); + const packagePolicyService = osqueryContext.service.getPackagePolicyService(); + const agentPolicyService = osqueryContext.service.getAgentPolicyService(); + + const { items: packagePolicies } = (await packagePolicyService?.list( + internalSavedObjectsClient, + { + kuery: `${PACKAGE_POLICY_SAVED_OBJECT_TYPE}.package.name:${OSQUERY_INTEGRATION_NAME}`, + perPage: 1000, + page: 1, + } + )) ?? { items: [] as PackagePolicy[] }; + const supportedPackagePolicyIds = filter(packagePolicies, (packagePolicy) => + satisfies(packagePolicy.package?.version ?? '', '>=0.6.0') + ); + const agentPolicyIds = uniq(map(supportedPackagePolicyIds, 'policy_id')); + + const agentPolicies = await agentPolicyService?.getByIds( + internalSavedObjectsClient, + agentPolicyIds + ); + + const agentPolicyById = mapKeys(agentPolicies, 'id'); + + const { platforms, overlap, policies } = processAggregations(esAgents?.aggregations); + + return response.ok({ + body: { + total: esAgents?.total ?? 0, + groups: { + platforms, + overlap, + policies: policies.map((p) => { + const name = agentPolicyById[p.id]?.name ?? p.name; + + return { + ...p, + name, + }; + }), + }, + agents: esAgents?.agents ?? [], + }, + }); } ); }; diff --git a/x-pack/plugins/osquery/server/routes/pack/utils.ts b/x-pack/plugins/osquery/server/routes/pack/utils.ts index a458e6edadfa1..3f3c9fa90c746 100644 --- a/x-pack/plugins/osquery/server/routes/pack/utils.ts +++ b/x-pack/plugins/osquery/server/routes/pack/utils.ts @@ -21,7 +21,16 @@ export const convertPackQueriesToSO = (queries) => const ecsMapping = value.ecs_mapping && convertECSMappingToArray(value.ecs_mapping); acc.push({ id: key, - ...pick(value, ['name', 'query', 'interval', 'platform', 'version', 'snapshot', 'removed']), + ...pick(value, [ + 'name', + 'query', + 'interval', + 'platform', + 'version', + 'snapshot', + 'removed', + 'timeout', + ]), ...(ecsMapping ? { ecs_mapping: ecsMapping } : {}), }); @@ -32,6 +41,7 @@ export const convertPackQueriesToSO = (queries) => name: string; query: string; interval: number; + timeout?: number; snapshot?: boolean; removed?: boolean; ecs_mapping?: Record; diff --git a/x-pack/plugins/osquery/server/routes/saved_query/create_saved_query_route.ts b/x-pack/plugins/osquery/server/routes/saved_query/create_saved_query_route.ts index bccd521f6323d..d59f1c5ba0f8d 100644 --- a/x-pack/plugins/osquery/server/routes/saved_query/create_saved_query_route.ts +++ b/x-pack/plugins/osquery/server/routes/saved_query/create_saved_query_route.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { isEmpty, pickBy, some, isBoolean } from 'lodash'; +import { isEmpty, pickBy, some, isBoolean, isNumber } from 'lodash'; import type { IRouter } from '@kbn/core/server'; import type { CreateSavedQueryRequestSchemaDecoded } from '../../../common/api'; import { API_VERSIONS } from '../../../common/constants'; @@ -50,6 +50,7 @@ export const createSavedQueryRoute = (router: IRouter, osqueryContext: OsqueryAp interval, snapshot, removed, + timeout, // eslint-disable-next-line @typescript-eslint/naming-convention ecs_mapping, } = request.body; @@ -80,13 +81,14 @@ export const createSavedQueryRoute = (router: IRouter, osqueryContext: OsqueryAp interval, snapshot, removed, + timeout, ecs_mapping: convertECSMappingToArray(ecs_mapping), created_by: currentUser, created_at: new Date().toISOString(), updated_by: currentUser, updated_at: new Date().toISOString(), }, - (value) => !isEmpty(value) || isBoolean(value) + (value) => !isEmpty(value) || isBoolean(value) || isNumber(value) ) ); @@ -102,6 +104,7 @@ export const createSavedQueryRoute = (router: IRouter, osqueryContext: OsqueryAp snapshot: attributes.snapshot, version: attributes.version, interval: attributes.interval, + timeout: attributes.timeout, platform: attributes.platform, query: attributes.query, updated_at: attributes.updated_at, @@ -109,7 +112,7 @@ export const createSavedQueryRoute = (router: IRouter, osqueryContext: OsqueryAp saved_object_id: savedQuerySO.id, ecs_mapping, }, - (value) => !isEmpty(value) + (value) => !isEmpty(value) || isNumber(value) ); return response.ok({ diff --git a/x-pack/plugins/osquery/server/routes/saved_query/find_saved_query_route.ts b/x-pack/plugins/osquery/server/routes/saved_query/find_saved_query_route.ts index a176d581329b5..88ccc120d0fd6 100644 --- a/x-pack/plugins/osquery/server/routes/saved_query/find_saved_query_route.ts +++ b/x-pack/plugins/osquery/server/routes/saved_query/find_saved_query_route.ts @@ -73,6 +73,7 @@ export const findSavedQueryRoute = (router: IRouter, osqueryContext: OsqueryAppC description, id, interval, + timeout, platform, query, removed, @@ -94,6 +95,7 @@ export const findSavedQueryRoute = (router: IRouter, osqueryContext: OsqueryAppC version, ecs_mapping: ecsMapping, interval, + timeout, platform, query, updated_at: updatedAt, diff --git a/x-pack/plugins/osquery/server/routes/saved_query/read_saved_query_route.ts b/x-pack/plugins/osquery/server/routes/saved_query/read_saved_query_route.ts index fb355c8b732b0..706304300c40a 100644 --- a/x-pack/plugins/osquery/server/routes/saved_query/read_saved_query_route.ts +++ b/x-pack/plugins/osquery/server/routes/saved_query/read_saved_query_route.ts @@ -64,6 +64,7 @@ export const readSavedQueryRoute = (router: IRouter, osqueryContext: OsqueryAppC description, id, interval, + timeout, platform, query, removed, @@ -85,6 +86,7 @@ export const readSavedQueryRoute = (router: IRouter, osqueryContext: OsqueryAppC version, ecs_mapping: ecsMapping, interval, + timeout, platform, query, updated_at: updatedAt, diff --git a/x-pack/plugins/osquery/server/routes/saved_query/types.ts b/x-pack/plugins/osquery/server/routes/saved_query/types.ts index 3e3ecf9d18844..07f1a812cf9f6 100644 --- a/x-pack/plugins/osquery/server/routes/saved_query/types.ts +++ b/x-pack/plugins/osquery/server/routes/saved_query/types.ts @@ -11,6 +11,7 @@ export interface SavedQueryResponse { description: string | undefined; query: string; interval: number | string; + timeout?: number; snapshot?: boolean; removed?: boolean; platform?: string; @@ -29,6 +30,7 @@ export interface UpdateSavedQueryResponse { description: string | undefined; query: string; interval: number | string; + timeout?: number; snapshot?: boolean; removed?: boolean; platform?: string; diff --git a/x-pack/plugins/osquery/server/routes/saved_query/update_saved_query_route.ts b/x-pack/plugins/osquery/server/routes/saved_query/update_saved_query_route.ts index d6cd11805c57a..f6bcad9d4bed4 100644 --- a/x-pack/plugins/osquery/server/routes/saved_query/update_saved_query_route.ts +++ b/x-pack/plugins/osquery/server/routes/saved_query/update_saved_query_route.ts @@ -60,6 +60,7 @@ export const updateSavedQueryRoute = (router: IRouter, osqueryContext: OsqueryAp query, version, interval, + timeout, snapshot, removed, // eslint-disable-next-line @typescript-eslint/naming-convention @@ -102,6 +103,7 @@ export const updateSavedQueryRoute = (router: IRouter, osqueryContext: OsqueryAp query, version, interval, + timeout, snapshot, removed, ecs_mapping: convertECSMappingToArray(ecs_mapping), @@ -133,6 +135,7 @@ export const updateSavedQueryRoute = (router: IRouter, osqueryContext: OsqueryAp version: attributes.version, ecs_mapping: attributes.ecs_mapping, interval: attributes.interval, + timeout: attributes.timeout, platform: attributes.platform, query: attributes.query, updated_at: attributes.updated_at, diff --git a/x-pack/plugins/osquery/server/search_strategy/osquery/factory/actions/all/query.all_actions.dsl.ts b/x-pack/plugins/osquery/server/search_strategy/osquery/factory/actions/all/query.all_actions.dsl.ts index 81c1e0541b8bd..fc1884a83fda7 100644 --- a/x-pack/plugins/osquery/server/search_strategy/osquery/factory/actions/all/query.all_actions.dsl.ts +++ b/x-pack/plugins/osquery/server/search_strategy/osquery/factory/actions/all/query.all_actions.dsl.ts @@ -9,9 +9,9 @@ import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import type { ISearchRequestParams } from '@kbn/data-plugin/common'; import { AGENT_ACTIONS_INDEX } from '@kbn/fleet-plugin/common'; +import type { AgentsRequestOptions } from '../../../../../../common/search_strategy/osquery/agents'; import { getQueryFilter } from '../../../../../utils/build_query'; import { ACTIONS_INDEX } from '../../../../../../common/constants'; -import type { AgentsRequestOptions } from '../../../../../../common/search_strategy'; export const buildActionsQuery = ({ kuery = '', @@ -23,7 +23,7 @@ export const buildActionsQuery = ({ bool: { filter }, } = getQueryFilter({ filter: kuery }); - const dslQuery = { + return { allow_no_indices: true, index: componentTemplateExists ? `${ACTIONS_INDEX}*` : AGENT_ACTIONS_INDEX, ignore_unavailable: true, @@ -62,6 +62,4 @@ export const buildActionsQuery = ({ ], }, }; - - return dslQuery; }; diff --git a/x-pack/plugins/osquery/server/search_strategy/osquery/factory/actions/results/query.action_results.dsl.ts b/x-pack/plugins/osquery/server/search_strategy/osquery/factory/actions/results/query.action_results.dsl.ts index 47901f47b6593..830447e65be5f 100644 --- a/x-pack/plugins/osquery/server/search_strategy/osquery/factory/actions/results/query.action_results.dsl.ts +++ b/x-pack/plugins/osquery/server/search_strategy/osquery/factory/actions/results/query.action_results.dsl.ts @@ -8,6 +8,7 @@ import type { ISearchRequestParams } from '@kbn/data-plugin/common'; import { AGENT_ACTIONS_RESULTS_INDEX } from '@kbn/fleet-plugin/common'; import { isEmpty } from 'lodash'; +import moment from 'moment'; import { ACTION_RESPONSES_INDEX } from '../../../../../../common/constants'; import type { ActionResultsRequestOptions } from '../../../../../../common/search_strategy'; import { getQueryFilter } from '../../../../../utils/build_query'; @@ -15,19 +16,32 @@ import { getQueryFilter } from '../../../../../utils/build_query'; export const buildActionResultsQuery = ({ actionId, kuery, - // pagination: { activePage, querySize }, + startDate, sort, componentTemplateExists, }: ActionResultsRequestOptions): ISearchRequestParams => { - const actionIdQuery = `action_id: ${actionId}`; - let filter = actionIdQuery; + let filter = `action_id: ${actionId}`; if (!isEmpty(kuery)) { filter = filter + ` AND ${kuery}`; } - const filterQuery = getQueryFilter({ filter }); + const timeRangeFilter = + startDate && !isEmpty(startDate) + ? [ + { + range: { + started_at: { + gte: startDate, + lte: moment(startDate).clone().add(30, 'minutes').toISOString(), + }, + }, + }, + ] + : []; - const dslQuery = { + const filterQuery = [...timeRangeFilter, getQueryFilter({ filter })]; + + return { allow_no_indices: true, index: componentTemplateExists ? `${ACTION_RESPONSES_INDEX}-default*` @@ -84,6 +98,4 @@ export const buildActionResultsQuery = ({ ], }, }; - - return dslQuery; }; diff --git a/x-pack/plugins/osquery/server/search_strategy/osquery/factory/agents/index.ts b/x-pack/plugins/osquery/server/search_strategy/osquery/factory/agents/index.ts deleted file mode 100644 index 72bb97f1b8eaa..0000000000000 --- a/x-pack/plugins/osquery/server/search_strategy/osquery/factory/agents/index.ts +++ /dev/null @@ -1,46 +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 { IEsSearchResponse } from '@kbn/data-plugin/common'; -import { DEFAULT_MAX_TABLE_QUERY_SIZE } from '../../../../../common/constants'; -import type { - AgentsStrategyResponse, - AgentsRequestOptions, - OsqueryQueries, -} from '../../../../../common/search_strategy/osquery'; - -import type { Agent } from '../../../../../common/shared_imports'; -import { inspectStringifyObject } from '../../../../../common/utils/build_query'; -import type { OsqueryFactory } from '../types'; -import { buildAgentsQuery } from './query.all_agents.dsl'; - -export const allAgents: OsqueryFactory = { - buildDsl: (options: AgentsRequestOptions) => { - if (options.pagination && options.pagination.querySize >= DEFAULT_MAX_TABLE_QUERY_SIZE) { - throw new Error(`No query size above ${DEFAULT_MAX_TABLE_QUERY_SIZE}`); - } - - return buildAgentsQuery(options); - }, - parse: async ( - options: AgentsRequestOptions, - response: IEsSearchResponse - ): Promise => { - const inspect = { - dsl: [inspectStringifyObject(buildAgentsQuery(options))], - }; - - return { - ...response, - inspect, - edges: response.rawResponse.hits.hits.map((hit) => ({ - _id: hit._id, - ...hit._source, - })) as Agent[], - }; - }, -}; diff --git a/x-pack/plugins/osquery/server/search_strategy/osquery/factory/agents/query.all_agents.dsl.ts b/x-pack/plugins/osquery/server/search_strategy/osquery/factory/agents/query.all_agents.dsl.ts deleted file mode 100644 index b06f54900d259..0000000000000 --- a/x-pack/plugins/osquery/server/search_strategy/osquery/factory/agents/query.all_agents.dsl.ts +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import type { ISearchRequestParams } from '@kbn/data-plugin/common'; -import { AGENTS_INDEX } from '@kbn/fleet-plugin/common'; -import { isEmpty } from 'lodash'; -import { getQueryFilter } from '../../../../utils/build_query'; -import type { AgentsRequestOptions } from '../../../../../common/search_strategy'; - -export const buildAgentsQuery = ({ - kuery, - pagination: { cursorStart }, - sort, -}: AgentsRequestOptions): ISearchRequestParams => { - const activeQuery = `active: true`; - let filter = activeQuery; - if (!isEmpty(kuery)) { - filter = activeQuery + ` AND ${kuery}`; - } - - const filterQuery = getQueryFilter({ filter }); - - return { - allow_no_indices: true, - index: AGENTS_INDEX, - ignore_unavailable: true, - body: { - query: { - bool: { - filter: filterQuery, - }, - }, - aggs: { - platforms: { - terms: { - field: 'local_metadata.os.platform', - }, - }, - policies: { - terms: { - field: 'policy_id', - size: 2000, - }, - }, - }, - track_total_hits: true, - sort: [ - { - [sort.field]: { - order: sort.direction, - }, - }, - ], - size: 0, - from: cursorStart, - }, - }; -}; diff --git a/x-pack/plugins/osquery/server/search_strategy/osquery/factory/index.ts b/x-pack/plugins/osquery/server/search_strategy/osquery/factory/index.ts index d1af1cf36622a..747293630d694 100644 --- a/x-pack/plugins/osquery/server/search_strategy/osquery/factory/index.ts +++ b/x-pack/plugins/osquery/server/search_strategy/osquery/factory/index.ts @@ -9,7 +9,6 @@ import type { FactoryQueryTypes } from '../../../../common/search_strategy/osque import { OsqueryQueries } from '../../../../common/search_strategy/osquery'; import { allActions, actionDetails, actionResults } from './actions'; -import { allAgents } from './agents'; import { allResults } from './results'; import type { OsqueryFactory } from './types'; @@ -18,6 +17,5 @@ export const osqueryFactory: Record { const actionIdQuery = `action_id: ${actionId}`; @@ -25,9 +27,22 @@ export const buildResultsQuery = ({ filter = filter + ` AND ${kuery}`; } - const filterQuery = getQueryFilter({ filter }); + const timeRangeFilter = + startDate && !isEmpty(startDate) + ? [ + { + range: { + '@timestamp': { + gte: startDate, + lte: moment(startDate).clone().add(30, 'minutes').toISOString(), + }, + }, + }, + ] + : []; + const filterQuery = [...timeRangeFilter, getQueryFilter({ filter })]; - const dslQuery = { + return { allow_no_indices: true, index: `logs-${OSQUERY_INTEGRATION_NAME}.result*`, ignore_unavailable: true, @@ -58,6 +73,4 @@ export const buildResultsQuery = ({ })) ?? [], }, }; - - return dslQuery; }; diff --git a/x-pack/plugins/osquery/server/search_strategy/osquery/index.ts b/x-pack/plugins/osquery/server/search_strategy/osquery/index.ts index af14d84fa3637..898f53b17c552 100644 --- a/x-pack/plugins/osquery/server/search_strategy/osquery/index.ts +++ b/x-pack/plugins/osquery/server/search_strategy/osquery/index.ts @@ -45,6 +45,7 @@ export const osquerySearchStrategyProvider = ( ...('pagination' in request ? { pagination: request.pagination } : {}), ...('sort' in request ? { sort: request.sort } : {}), ...('actionId' in request ? { actionId: request.actionId } : {}), + ...('startDate' in request ? { startDate: request.startDate } : {}), ...('agentId' in request ? { agentId: request.agentId } : {}), } as StrategyRequestType; diff --git a/x-pack/plugins/painless_lab/server/index.ts b/x-pack/plugins/painless_lab/server/index.ts index d81147ed9e395..ad8203ecba194 100644 --- a/x-pack/plugins/painless_lab/server/index.ts +++ b/x-pack/plugins/painless_lab/server/index.ts @@ -7,7 +7,6 @@ import { offeringBasedSchema, schema, TypeOf } from '@kbn/config-schema'; import { PluginInitializerContext, PluginConfigDescriptor } from '@kbn/core/server'; -import { PainlessLabServerPlugin } from './plugin'; export const configSchema = schema.object({ enabled: offeringBasedSchema({ @@ -20,6 +19,7 @@ export const config: PluginConfigDescriptor = { schema: configSchema, }; -export const plugin = (ctx: PluginInitializerContext) => { +export const plugin = async (ctx: PluginInitializerContext) => { + const { PainlessLabServerPlugin } = await import('./plugin'); return new PainlessLabServerPlugin(ctx); }; diff --git a/x-pack/plugins/profiling/server/index.ts b/x-pack/plugins/profiling/server/index.ts index 25861fbcfc750..cbd429315cbb5 100644 --- a/x-pack/plugins/profiling/server/index.ts +++ b/x-pack/plugins/profiling/server/index.ts @@ -7,7 +7,6 @@ import { schema, TypeOf } from '@kbn/config-schema'; import type { PluginConfigDescriptor, PluginInitializerContext } from '@kbn/core/server'; -import { ProfilingPlugin } from './plugin'; /** * These properties are used to create both the Collector and the Symbolizer integrations @@ -56,7 +55,8 @@ export const config: PluginConfigDescriptor = { // This exports static code and TypeScript types, // as well as, Kibana Platform `plugin()` initializer. -export function plugin(initializerContext: PluginInitializerContext) { +export async function plugin(initializerContext: PluginInitializerContext) { + const { ProfilingPlugin } = await import('./plugin'); return new ProfilingPlugin(initializerContext); } diff --git a/x-pack/plugins/profiling_data_access/server/index.ts b/x-pack/plugins/profiling_data_access/server/index.ts index d979d22f4a011..c245297c86bd8 100644 --- a/x-pack/plugins/profiling_data_access/server/index.ts +++ b/x-pack/plugins/profiling_data_access/server/index.ts @@ -7,7 +7,6 @@ import { schema, TypeOf } from '@kbn/config-schema'; import type { PluginInitializerContext } from '@kbn/core/server'; -import { ProfilingDataAccessPlugin } from './plugin'; import type { ProfilingDataAccessPluginSetup, ProfilingDataAccessPluginStart } from './plugin'; const configSchema = schema.object({ @@ -29,6 +28,7 @@ export type ProfilingConfig = TypeOf; export type { ProfilingDataAccessPluginSetup, ProfilingDataAccessPluginStart }; -export function plugin(initializerContext: PluginInitializerContext) { +export async function plugin(initializerContext: PluginInitializerContext) { + const { ProfilingDataAccessPlugin } = await import('./plugin'); return new ProfilingDataAccessPlugin(initializerContext); } diff --git a/x-pack/plugins/remote_clusters/server/index.ts b/x-pack/plugins/remote_clusters/server/index.ts index 8325b869b150d..4702f6390d99a 100644 --- a/x-pack/plugins/remote_clusters/server/index.ts +++ b/x-pack/plugins/remote_clusters/server/index.ts @@ -6,9 +6,11 @@ */ import { PluginInitializerContext } from '@kbn/core/server'; -import { RemoteClustersServerPlugin } from './plugin'; export { config } from './config'; export type { RemoteClustersPluginSetup } from './plugin'; -export const plugin = (ctx: PluginInitializerContext) => new RemoteClustersServerPlugin(ctx); +export const plugin = async (ctx: PluginInitializerContext) => { + const { RemoteClustersServerPlugin } = await import('./plugin'); + return new RemoteClustersServerPlugin(ctx); +}; diff --git a/x-pack/plugins/reporting/README.md b/x-pack/plugins/reporting/README.md index 9b54ef6892014..c0c28c5c6fcd5 100644 --- a/x-pack/plugins/reporting/README.md +++ b/x-pack/plugins/reporting/README.md @@ -10,7 +10,7 @@ This should be deprecated. It is historically a customer driven endpoint. This This new endpoint is designed to have a more automation-friendly signature. It will replace csv_searchsource in the UI at some point, when there is more capacity in reporting. It will need a little more work to have parity: it needs to be able to export "unsaved" searches. ## Generate CSV -Although historically related to reporting, the CsvGenerator class has now be moved into its own package `@kbn/generate-csv` and `@kbn/generate-csv-types`. +Although historically related to reporting, the CsvGenerator class has now be moved into its own package `@kbn/generate-csv`. ## Serverless configuration There are several improvements made for reporting in serverless environments. Most changes are reflected in `reporting/server/config/schema.ts` for reference. diff --git a/x-pack/plugins/reporting/common/constants/export_types.ts b/x-pack/plugins/reporting/common/constants/export_types.ts new file mode 100644 index 0000000000000..20f8a63204e75 --- /dev/null +++ b/x-pack/plugins/reporting/common/constants/export_types.ts @@ -0,0 +1,54 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +// Export Type Sets +import { + CSV_JOB_TYPE, + CSV_JOB_TYPE_DEPRECATED, + CSV_JOB_TYPE_V2, + CSV_REPORT_TYPE, + CSV_REPORT_TYPE_V2, +} from '@kbn/reporting-export-types-csv-common'; +import { + PDF_JOB_TYPE, + PDF_JOB_TYPE_V2, + PDF_REPORT_TYPE, + PDF_REPORT_TYPE_V2, +} from '@kbn/reporting-export-types-pdf-common'; +import { + PNG_JOB_TYPE, + PNG_JOB_TYPE_V2, + PNG_REPORT_TYPE, + PNG_REPORT_TYPE_V2, +} from '@kbn/reporting-export-types-png-common'; + +export const reportTypes = [ + CSV_REPORT_TYPE, + CSV_REPORT_TYPE_V2, + PDF_REPORT_TYPE, + PDF_REPORT_TYPE_V2, + PNG_REPORT_TYPE, + PNG_REPORT_TYPE_V2, +]; + +export const jobTypes = [ + CSV_JOB_TYPE, + CSV_JOB_TYPE_V2, + PDF_JOB_TYPE, + PDF_JOB_TYPE_V2, + PNG_JOB_TYPE, + PNG_JOB_TYPE_V2, +]; + +export const USES_HEADLESS_JOB_TYPES = [ + PDF_JOB_TYPE, + PNG_JOB_TYPE, + PDF_JOB_TYPE_V2, + PNG_JOB_TYPE_V2, +]; + +export const DEPRECATED_JOB_TYPES = [CSV_JOB_TYPE_DEPRECATED]; diff --git a/x-pack/plugins/reporting/common/constants/index.ts b/x-pack/plugins/reporting/common/constants/index.ts index f02ea766da66b..44e90356027bc 100644 --- a/x-pack/plugins/reporting/common/constants/index.ts +++ b/x-pack/plugins/reporting/common/constants/index.ts @@ -5,98 +5,9 @@ * 2.0. */ -import { CONTENT_TYPE_CSV } from '@kbn/generate-csv/src/constants'; -import * as jobTypes from './job_types'; -import * as reportTypes from './report_types'; - -const { PDF_JOB_TYPE, PDF_JOB_TYPE_V2, PNG_JOB_TYPE, PNG_JOB_TYPE_V2 } = jobTypes; - -export const PLUGIN_ID = 'reporting'; - -export const REPORTING_TRANSACTION_TYPE = PLUGIN_ID; - -export const REPORTING_SYSTEM_INDEX = '.reporting'; - -export const JOB_COMPLETION_NOTIFICATIONS_SESSION_KEY = - 'xpack.reporting.jobCompletionNotifications'; - -export const ALLOWED_JOB_CONTENT_TYPES = [ - 'application/json', - 'application/pdf', - CONTENT_TYPE_CSV, - 'image/png', - 'text/plain', -]; - -type ReportTypeDeclaration = typeof reportTypes; -export type ReportTypes = ReportTypeDeclaration[keyof ReportTypeDeclaration]; - -type JobTypeDeclaration = typeof jobTypes; -export type JobTypes = JobTypeDeclaration[keyof JobTypeDeclaration]; - -export const CSV_SEARCHSOURCE_IMMEDIATE_TYPE = 'csv_searchsource_immediate'; - -// This is deprecated because it lacks support for runtime fields -// but the extension points are still needed for pre-existing scripted automation, until 8.0 -export const CSV_REPORT_TYPE_DEPRECATED = 'CSV'; -export const CSV_JOB_TYPE_DEPRECATED = 'csv'; - -export const USES_HEADLESS_JOB_TYPES = [ - PDF_JOB_TYPE, - PNG_JOB_TYPE, - PDF_JOB_TYPE_V2, - PNG_JOB_TYPE_V2, -]; - -export const DEPRECATED_JOB_TYPES = [CSV_JOB_TYPE_DEPRECATED]; - -// Licenses -export const LICENSE_TYPE_TRIAL = 'trial' as const; -export const LICENSE_TYPE_BASIC = 'basic' as const; -export const LICENSE_TYPE_CLOUD_STANDARD = 'standard' as const; -export const LICENSE_TYPE_GOLD = 'gold' as const; -export const LICENSE_TYPE_PLATINUM = 'platinum' as const; -export const LICENSE_TYPE_ENTERPRISE = 'enterprise' as const; - -export const ILM_POLICY_NAME = 'kibana-reporting'; - -// Usage counter types -export const API_USAGE_COUNTER_TYPE = 'reportingApi'; -export const API_USAGE_ERROR_TYPE = 'reportingApiError'; - -// Management UI route -export const REPORTING_MANAGEMENT_HOME = '/app/management/insightsAndAlerting/reporting'; - -export const REPORTING_REDIRECT_LOCATOR_STORE_KEY = '__REPORTING_REDIRECT_LOCATOR_STORE_KEY__'; - -/** - * A way to get the client side route for the reporting redirect app. - * - * TODO: Add a job ID and a locator to use so that we can redirect without expecting state to - * be injected to the page - */ -export const getRedirectAppPath = () => { - return '/app/reportingRedirect'; -}; - -// Statuses -export enum JOB_STATUSES { - PENDING = 'pending', - PROCESSING = 'processing', - COMPLETED = 'completed', - FAILED = 'failed', - WARNINGS = 'completed_with_warnings', -} +export * from './routes'; +export * from './export_types'; // Test Subjects export const REPORT_TABLE_ID = 'reportJobListing'; export const REPORT_TABLE_ROW_ID = 'reportJobRow'; - -// Job params require a `version` field as of 7.15.0. For older jobs set with -// automation that have no version value in the job params, we assume the -// intended version is 7.14.0 -export const UNVERSIONED_VERSION = '7.14.0'; - -export * from './job_types'; -export * from './report_types'; -export * from './routes'; diff --git a/x-pack/plugins/reporting/common/constants/report_types.ts b/x-pack/plugins/reporting/common/constants/report_types.ts deleted file mode 100644 index b66e00de7407f..0000000000000 --- a/x-pack/plugins/reporting/common/constants/report_types.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. - */ - -// Export Type Definitions -export const CSV_REPORT_TYPE = 'csv_searchsource'; -export const CSV_REPORT_TYPE_V2 = 'csv_v2'; - -export const PDF_REPORT_TYPE = 'printablePdf'; -export const PDF_REPORT_TYPE_V2 = 'printablePdfV2'; - -export const PNG_REPORT_TYPE = 'PNG'; -export const PNG_REPORT_TYPE_V2 = 'pngV2'; diff --git a/x-pack/plugins/reporting/common/errors/map_to_reporting_error.test.ts b/x-pack/plugins/reporting/common/errors/map_to_reporting_error.test.ts index 5b22591e7a16a..5e8193deaf07f 100644 --- a/x-pack/plugins/reporting/common/errors/map_to_reporting_error.test.ts +++ b/x-pack/plugins/reporting/common/errors/map_to_reporting_error.test.ts @@ -5,15 +5,15 @@ * 2.0. */ -import { mapToReportingError } from './map_to_reporting_error'; -import { errors } from '@kbn/screenshotting-plugin/common'; import { - UnknownError, BrowserCouldNotLaunchError, - BrowserUnexpectedlyClosedError, BrowserScreenshotError, + BrowserUnexpectedlyClosedError, InvalidLayoutParametersError, + UnknownError, } from '@kbn/reporting-common'; +import { mapToReportingError } from './map_to_reporting_error'; +import { errors } from '@kbn/screenshotting-plugin/common'; describe('mapToReportingError', () => { test('Non-Error values', () => { diff --git a/x-pack/plugins/reporting/common/index.ts b/x-pack/plugins/reporting/common/index.ts deleted file mode 100644 index 36c9f99628778..0000000000000 --- a/x-pack/plugins/reporting/common/index.ts +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -/** - * Common types that are documented in the Public API - */ -export type { - BaseParams, - BaseParamsV2, - BasePayload, - BasePayloadV2, - JobAppParamsPDF, - JobAppParamsPDFV2, - LocatorParams, -} from './types'; diff --git a/x-pack/plugins/reporting/common/job_utils.ts b/x-pack/plugins/reporting/common/job_utils.ts index c1fd2eb5eb8c4..580f2d7467113 100644 --- a/x-pack/plugins/reporting/common/job_utils.ts +++ b/x-pack/plugins/reporting/common/job_utils.ts @@ -5,14 +5,9 @@ * 2.0. */ -import { - CSV_JOB_TYPE, - PDF_JOB_TYPE, - PNG_JOB_TYPE, - PDF_JOB_TYPE_V2, - PNG_JOB_TYPE_V2, - CSV_JOB_TYPE_DEPRECATED, -} from './constants'; +import { CSV_JOB_TYPE, CSV_JOB_TYPE_DEPRECATED } from '@kbn/reporting-export-types-csv-common'; +import { PDF_JOB_TYPE, PDF_JOB_TYPE_V2 } from '@kbn/reporting-export-types-pdf-common'; +import { PNG_JOB_TYPE, PNG_JOB_TYPE_V2 } from '@kbn/reporting-export-types-png-common'; // TODO: Remove this code once everyone is using the new PDF format, then we can also remove the legacy // export type entirely diff --git a/x-pack/plugins/reporting/common/schema_utils.test.ts b/x-pack/plugins/reporting/common/schema_utils.test.ts deleted file mode 100644 index 6e9bb2db75437..0000000000000 --- a/x-pack/plugins/reporting/common/schema_utils.test.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 moment from 'moment'; -import { numberToDuration } from './schema_utils'; - -describe('Schema Utils', () => { - it('numberToDuration converts a number/Duration into a Duration object', () => { - expect(numberToDuration(500)).toMatchInlineSnapshot(`"PT0.5S"`); - expect(numberToDuration(moment.duration(1, 'hour'))).toMatchInlineSnapshot(`"PT1H"`); - }); -}); diff --git a/x-pack/plugins/reporting/common/schema_utils.ts b/x-pack/plugins/reporting/common/schema_utils.ts deleted file mode 100644 index 798440bfbb69c..0000000000000 --- a/x-pack/plugins/reporting/common/schema_utils.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 { ByteSizeValue } from '@kbn/config-schema'; -import moment from 'moment'; - -/* - * For cleaner code: use these functions when a config schema value could be - * one type or another. This allows you to treat the value as one type. - */ - -export const durationToNumber = (value: number | moment.Duration): number => { - if (typeof value === 'number') { - return value; - } - return value.asMilliseconds(); -}; - -export const numberToDuration = (value: number | moment.Duration): moment.Duration => { - if (typeof value === 'number') { - return moment.duration(value, 'milliseconds'); - } - return value; -}; - -export const byteSizeValueToNumber = (value: number | ByteSizeValue) => { - if (typeof value === 'number') { - return value; - } - - return value.getValueInBytes(); -}; diff --git a/x-pack/plugins/reporting/common/test/fixtures.ts b/x-pack/plugins/reporting/common/test/fixtures.ts index 1a78e52199534..823785c4eb273 100644 --- a/x-pack/plugins/reporting/common/test/fixtures.ts +++ b/x-pack/plugins/reporting/common/test/fixtures.ts @@ -5,7 +5,8 @@ * 2.0. */ -import type { ReportApiJSON } from '../types'; +import { JOB_STATUS } from '@kbn/reporting-common'; +import { ReportApiJSON } from '@kbn/reporting-common/types'; import type { ReportMock } from './types'; const buildMockReport = (baseObj: ReportMock): ReportApiJSON => ({ @@ -43,7 +44,7 @@ export const mockJobs: ReportApiJSON[] = [ }, ], } as any, - status: 'pending', + status: JOB_STATUS.PENDING, }), buildMockReport({ id: 'k90e51pk1ieucbae0c3t8wo1', @@ -56,7 +57,7 @@ export const mockJobs: ReportApiJSON[] = [ title: 'My Canvas Workpad', }, started_at: '2020-04-14T21:01:14.526Z', - status: 'processing', + status: JOB_STATUS.PROCESSING, }), buildMockReport({ id: 'k90cmthd1gv8cbae0c2le8bo', @@ -71,7 +72,7 @@ export const mockJobs: ReportApiJSON[] = [ title: 'My Canvas Workpad', }, started_at: '2020-04-14T20:19:04.073Z', - status: 'completed', + status: JOB_STATUS.COMPLETED, }), buildMockReport({ id: 'k906958e1d4wcbae0c9hip1a', @@ -92,7 +93,7 @@ export const mockJobs: ReportApiJSON[] = [ title: 'My Canvas Workpad', }, started_at: '2020-04-14T17:20:29.444Z', - status: 'completed_with_warnings', + status: JOB_STATUS.WARNINGS, }), buildMockReport({ id: 'k9067y2a1d4wcbae0cad38n0', @@ -107,7 +108,7 @@ export const mockJobs: ReportApiJSON[] = [ title: 'My Canvas Workpad', }, started_at: '2020-04-14T17:19:39.883Z', - status: 'completed', + status: JOB_STATUS.COMPLETED, }), buildMockReport({ id: 'k9067s1m1d4wcbae0cdnvcms', @@ -122,7 +123,7 @@ export const mockJobs: ReportApiJSON[] = [ title: 'My Canvas Workpad', }, started_at: '2020-04-14T17:19:25.247Z', - status: 'completed', + status: JOB_STATUS.COMPLETED, }), buildMockReport({ id: 'k9065q3s1d4wcbae0c00fxlh', @@ -137,7 +138,7 @@ export const mockJobs: ReportApiJSON[] = [ title: 'My Canvas Workpad', }, started_at: '2020-04-14T17:17:50.379Z', - status: 'completed', + status: JOB_STATUS.COMPLETED, }), buildMockReport({ id: 'k905zdw11d34cbae0c3y6tzh', @@ -153,7 +154,7 @@ export const mockJobs: ReportApiJSON[] = [ isDeprecated: true, }, started_at: '2020-04-14T17:12:52.431Z', - status: 'completed', + status: JOB_STATUS.COMPLETED, }), buildMockReport({ id: 'k8t4ylcb07mi9d006214ifyg', @@ -169,6 +170,6 @@ export const mockJobs: ReportApiJSON[] = [ isDeprecated: true, }, started_at: '2020-04-09T19:09:54.570Z', - status: 'completed', + status: JOB_STATUS.COMPLETED, }), ]; diff --git a/x-pack/plugins/reporting/common/test/types.ts b/x-pack/plugins/reporting/common/test/types.ts index 83ebc1e3358cb..5a4b7ed8530a6 100644 --- a/x-pack/plugins/reporting/common/test/types.ts +++ b/x-pack/plugins/reporting/common/test/types.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { ReportApiJSON } from '../types'; +import { ReportApiJSON } from '@kbn/reporting-common/types'; /** @internal */ export interface PayloadMock { diff --git a/x-pack/plugins/reporting/common/types.ts b/x-pack/plugins/reporting/common/types.ts new file mode 100644 index 0000000000000..09d1dc8f43e31 --- /dev/null +++ b/x-pack/plugins/reporting/common/types.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 { jobTypes, reportTypes } from './constants'; + +type ReportTypeDeclaration = typeof reportTypes; +export type ReportTypes = ReportTypeDeclaration[keyof ReportTypeDeclaration]; + +type JobTypeDeclaration = typeof jobTypes; +export type JobTypes = JobTypeDeclaration[keyof JobTypeDeclaration]; diff --git a/x-pack/plugins/reporting/common/types/base.ts b/x-pack/plugins/reporting/common/types/base.ts deleted file mode 100644 index 5f5a6f360c2a4..0000000000000 --- a/x-pack/plugins/reporting/common/types/base.ts +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import type { Ensure, SerializableRecord } from '@kbn/utility-types'; -import type { LayoutParams } from '@kbn/screenshotting-plugin/common'; -import { LocatorParams } from './url'; - -export type JobId = string; - -/** - * @deprecated - */ -export type BaseParams = Ensure< - { - layout?: LayoutParams; - objectType: string; - title: string; - browserTimezone: string; // to format dates in the user's time zone - version: string; // to handle any state migrations - }, - SerializableRecord ->; - -/** - * Report job parameters that an application must return from its - * getSharingData function. - */ -export type BaseParamsV2 = BaseParams & { - locatorParams: LocatorParams[]; -}; - -/** - * @deprecated - */ -export interface BasePayload extends BaseParams { - headers: string; - spaceId?: string; - isDeprecated?: boolean; -} - -/** - * Report job parameters, after they are processed in the request handler. - */ -export interface BasePayloadV2 extends BaseParamsV2 { - headers: string; - spaceId?: string; - isDeprecated?: boolean; -} diff --git a/x-pack/plugins/reporting/common/types/export_types/csv_searchsource.ts b/x-pack/plugins/reporting/common/types/export_types/csv_searchsource.ts deleted file mode 100644 index 9943deb642e88..0000000000000 --- a/x-pack/plugins/reporting/common/types/export_types/csv_searchsource.ts +++ /dev/null @@ -1,17 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import type { SerializedSearchSourceFields } from '@kbn/data-plugin/common'; -import type { BaseParams, BasePayload } from '../base'; - -interface BaseParamsCSV { - searchSource: SerializedSearchSourceFields; - columns?: string[]; -} - -export type JobParamsCSV = BaseParamsCSV & BaseParams; -export type TaskPayloadCSV = BaseParamsCSV & BasePayload; diff --git a/x-pack/plugins/reporting/common/types/export_types/csv_searchsource_immediate.ts b/x-pack/plugins/reporting/common/types/export_types/csv_searchsource_immediate.ts deleted file mode 100644 index b7954f3b936d8..0000000000000 --- a/x-pack/plugins/reporting/common/types/export_types/csv_searchsource_immediate.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 type { SerializedSearchSourceFields } from '@kbn/data-plugin/common'; - -export interface FakeRequest { - headers: Record; -} - -export interface JobParamsDownloadCSV { - browserTimezone: string; - title: string; - searchSource: SerializedSearchSourceFields; - columns?: string[]; -} - -export interface SavedObjectServiceError { - statusCode: number; - error?: string; - message?: string; -} diff --git a/x-pack/plugins/reporting/common/types/export_types/csv_v2.ts b/x-pack/plugins/reporting/common/types/export_types/csv_v2.ts deleted file mode 100644 index f56295ca651d5..0000000000000 --- a/x-pack/plugins/reporting/common/types/export_types/csv_v2.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 { BaseParamsV2, BasePayloadV2 } from '..'; -interface CsvFromSavedObjectBase { - objectType: 'search'; -} - -/** - * Makes title optional, as it can be derived from the saved search object - */ -export type JobParamsCsvFromSavedObject = CsvFromSavedObjectBase & - Omit & { title?: string }; - -/** - * - */ -export type TaskPayloadCsvFromSavedObject = CsvFromSavedObjectBase & BasePayloadV2; diff --git a/x-pack/plugins/reporting/common/types/export_types/png.ts b/x-pack/plugins/reporting/common/types/export_types/png.ts deleted file mode 100644 index 4a5367c754f4c..0000000000000 --- a/x-pack/plugins/reporting/common/types/export_types/png.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 type { LayoutParams } from '@kbn/screenshotting-plugin/common'; -import type { BaseParams, BasePayload } from '../base'; - -interface BaseParamsPNG { - layout: LayoutParams; - forceNow?: string; - relativeUrl: string; -} - -// Job params: structure of incoming user request data -/** - * @deprecated - */ -export type JobParamsPNGDeprecated = BaseParamsPNG & BaseParams; - -// Job payload: structure of stored job data provided by create_job -export type TaskPayloadPNG = BaseParamsPNG & BasePayload; diff --git a/x-pack/plugins/reporting/common/types/export_types/printable_pdf.ts b/x-pack/plugins/reporting/common/types/export_types/printable_pdf.ts deleted file mode 100644 index 240cc778b269d..0000000000000 --- a/x-pack/plugins/reporting/common/types/export_types/printable_pdf.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 type { LayoutParams } from '@kbn/screenshotting-plugin/common'; -import type { BaseParams, BasePayload } from '../base'; - -interface BaseParamsPDF { - layout: LayoutParams; - relativeUrls: string[]; - isDeprecated?: boolean; -} - -// Job params: structure of incoming user request data, after being parsed from RISON - -/** - * @deprecated - */ -export type JobParamsPDFDeprecated = BaseParamsPDF & BaseParams; - -/** - * @deprecated - */ -export type JobAppParamsPDF = Omit; - -/** - * Structure of stored job data provided by create_job - */ -export interface TaskPayloadPDF extends BasePayload { - layout: LayoutParams; - forceNow?: string; - objects: Array<{ relativeUrl: string }>; -} diff --git a/x-pack/plugins/reporting/common/types/export_types/printable_pdf_v2.ts b/x-pack/plugins/reporting/common/types/export_types/printable_pdf_v2.ts deleted file mode 100644 index 58462b84c5eec..0000000000000 --- a/x-pack/plugins/reporting/common/types/export_types/printable_pdf_v2.ts +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import type { LayoutParams } from '@kbn/screenshotting-plugin/common'; -import type { LocatorParams } from '../url'; -import type { BaseParams, BasePayload } from '../base'; - -interface BaseParamsPDFV2 { - layout: LayoutParams; - - /** - * This value is used to re-create the same visual state as when the report was requested as well as navigate to the correct page. - */ - locatorParams: LocatorParams[]; -} - -// Job params: structure of incoming user request data, after being parsed from RISON -export type JobParamsPDFV2 = BaseParamsPDFV2 & BaseParams; - -export type JobAppParamsPDFV2 = Omit; - -// Job payload: structure of stored job data provided by create_job -export interface TaskPayloadPDFV2 extends BasePayload, BaseParamsPDFV2 { - layout: LayoutParams; - /** - * The value of forceNow is injected server-side every time a given report is generated. - */ - forceNow: string; -} diff --git a/x-pack/plugins/reporting/kibana.jsonc b/x-pack/plugins/reporting/kibana.jsonc index e89e750ebe98c..55518519a5898 100644 --- a/x-pack/plugins/reporting/kibana.jsonc +++ b/x-pack/plugins/reporting/kibana.jsonc @@ -30,7 +30,7 @@ "security", "spaces", "usageCollection", - "screenshotting", + "screenshotting" ], "requiredBundles": [ "kibanaReact", diff --git a/x-pack/plugins/reporting/public/lib/ilm_policy_status_context.tsx b/x-pack/plugins/reporting/public/lib/ilm_policy_status_context.tsx index 78b2e77d09aee..8c0013b14f95a 100644 --- a/x-pack/plugins/reporting/public/lib/ilm_policy_status_context.tsx +++ b/x-pack/plugins/reporting/public/lib/ilm_policy_status_context.tsx @@ -7,8 +7,7 @@ import type { FunctionComponent } from 'react'; import React, { createContext, useContext } from 'react'; - -import { IlmPolicyStatusResponse } from '../../common/types'; +import type { IlmPolicyStatusResponse } from '@kbn/reporting-common/types'; import { useCheckIlmPolicyStatus } from './reporting_api_client'; diff --git a/x-pack/plugins/reporting/public/lib/job.test.ts b/x-pack/plugins/reporting/public/lib/job.test.ts index 8e6ebe51cc66d..3f1e64d57daf8 100644 --- a/x-pack/plugins/reporting/public/lib/job.test.ts +++ b/x-pack/plugins/reporting/public/lib/job.test.ts @@ -5,8 +5,8 @@ * 2.0. */ +import { jobTypes } from '../../common/constants'; import { mockJobs } from '../../common/test'; -import * as jobTypes from '../../common/constants/job_types'; import { Job } from './job'; describe('Job', () => { diff --git a/x-pack/plugins/reporting/public/lib/job.tsx b/x-pack/plugins/reporting/public/lib/job.tsx index 6ce8617d70359..9aadb06bf5cc8 100644 --- a/x-pack/plugins/reporting/public/lib/job.tsx +++ b/x-pack/plugins/reporting/public/lib/job.tsx @@ -5,12 +5,12 @@ * 2.0. */ -import { EuiText, EuiTextColor } from '@elastic/eui'; -import { i18n } from '@kbn/i18n'; -import { TaskRunResult } from '@kbn/reporting-common'; import moment from 'moment'; import React from 'react'; -import { JobTypes, JOB_STATUSES } from '../../common/constants'; + +import { EuiText, EuiTextColor } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +import { JOB_STATUS } from '@kbn/reporting-common'; import type { BaseParamsV2, JobId, @@ -18,9 +18,12 @@ import type { ReportFields, ReportOutput, ReportSource, -} from '../../common/types'; + TaskRunResult, +} from '@kbn/reporting-common/types'; + +import { JobTypes } from '../../common/types'; -const { COMPLETED, FAILED, PENDING, PROCESSING, WARNINGS } = JOB_STATUSES; +const { COMPLETED, FAILED, PENDING, PROCESSING, WARNINGS } = JOB_STATUS; type ReportPayload = ReportSource['payload']; @@ -45,7 +48,7 @@ export class Job { public readonly created_at: ReportSource['created_at']; public readonly started_at: ReportSource['started_at']; public readonly completed_at: ReportSource['completed_at']; - public readonly status: JOB_STATUSES; // FIXME: can not use ReportSource['status'] due to type mismatch + public readonly status: JOB_STATUS; // FIXME: can not use ReportSource['status'] due to type mismatch public readonly attempts: ReportSource['attempts']; public readonly max_attempts: ReportSource['max_attempts']; @@ -79,7 +82,7 @@ export class Job { this.created_at = report.created_at; this.started_at = report.started_at; this.completed_at = report.completed_at; - this.status = report.status as JOB_STATUSES; + this.status = report.status as JOB_STATUS; this.attempts = report.attempts; this.max_attempts = report.max_attempts; @@ -164,7 +167,7 @@ export class Job { } public get isDownloadReady(): boolean { - return this.status === JOB_STATUSES.COMPLETED || this.status === JOB_STATUSES.WARNINGS; + return this.status === JOB_STATUS.COMPLETED || this.status === JOB_STATUS.WARNINGS; } public get prettyJobTypeName(): undefined | string { @@ -179,6 +182,7 @@ export class Job { return i18n.translate('xpack.reporting.jobType.pngOutputName', { defaultMessage: 'PNG', }); + case 'csv_v2': case 'csv_searchsource': return i18n.translate('xpack.reporting.jobType.csvOutputName', { defaultMessage: 'CSV', @@ -319,7 +323,7 @@ export class Job { } } -const jobStatusLabelsMap = new Map([ +const jobStatusLabelsMap = new Map([ [ PENDING, i18n.translate('xpack.reporting.jobStatuses.pendingText', { diff --git a/x-pack/plugins/reporting/public/lib/license_check.ts b/x-pack/plugins/reporting/public/lib/license_check.ts index 80ecaefe8a853..6145d9b02f7e8 100644 --- a/x-pack/plugins/reporting/public/lib/license_check.ts +++ b/x-pack/plugins/reporting/public/lib/license_check.ts @@ -6,7 +6,7 @@ */ import { LicenseCheck } from '@kbn/licensing-plugin/public'; -import { LicenseCheckResults } from '../../common/types'; +import { LicenseCheckResults } from '@kbn/reporting-common/types'; export const checkLicense = (checkResults: LicenseCheck): LicenseCheckResults => { switch (checkResults.state) { diff --git a/x-pack/plugins/reporting/public/lib/reporting_api_client/hooks.ts b/x-pack/plugins/reporting/public/lib/reporting_api_client/hooks.ts index 8410ec8f82019..5ede6e11ee78a 100644 --- a/x-pack/plugins/reporting/public/lib/reporting_api_client/hooks.ts +++ b/x-pack/plugins/reporting/public/lib/reporting_api_client/hooks.ts @@ -5,8 +5,8 @@ * 2.0. */ +import { IlmPolicyStatusResponse } from '@kbn/reporting-common/types'; import { INTERNAL_ROUTES } from '../../../common/constants'; -import { IlmPolicyStatusResponse } from '../../../common/types'; import { useKibana, useRequest, UseRequestResponse } from '../../shared_imports'; export const useCheckIlmPolicyStatus = (): UseRequestResponse => { diff --git a/x-pack/plugins/reporting/public/lib/reporting_api_client/reporting_api_client.test.ts b/x-pack/plugins/reporting/public/lib/reporting_api_client/reporting_api_client.test.ts index 8737c80e969f8..87483e98fe5dd 100644 --- a/x-pack/plugins/reporting/public/lib/reporting_api_client/reporting_api_client.test.ts +++ b/x-pack/plugins/reporting/public/lib/reporting_api_client/reporting_api_client.test.ts @@ -5,9 +5,8 @@ * 2.0. */ -jest.mock('moment', () => ({ tz: { guess: jest.fn() } })); +import { tz } from 'moment-timezone'; -import { tz } from 'moment'; import { HttpSetup, IUiSettingsClient } from '@kbn/core/public'; import { httpServiceMock, uiSettingsServiceMock } from '@kbn/core/public/mocks'; import { Job } from '../job'; diff --git a/x-pack/plugins/reporting/public/lib/reporting_api_client/reporting_api_client.ts b/x-pack/plugins/reporting/public/lib/reporting_api_client/reporting_api_client.ts index 7e30866474991..37b8c60f4fe16 100644 --- a/x-pack/plugins/reporting/public/lib/reporting_api_client/reporting_api_client.ts +++ b/x-pack/plugins/reporting/public/lib/reporting_api_client/reporting_api_client.ts @@ -8,17 +8,16 @@ import { ELASTIC_INTERNAL_ORIGIN_QUERY_PARAM } from '@kbn/core-http-common'; import type { HttpFetchQuery } from '@kbn/core/public'; import { HttpSetup, IUiSettingsClient } from '@kbn/core/public'; import { i18n } from '@kbn/i18n'; +import { + REPORTING_MANAGEMENT_HOME, + buildKibanaPath, + getRedirectAppPath, +} from '@kbn/reporting-common'; +import { BaseParams, JobId, ManagementLinkFn, ReportApiJSON } from '@kbn/reporting-common/types'; import rison from '@kbn/rison'; import moment from 'moment'; import { stringify } from 'query-string'; -import { buildKibanaPath } from '../../../common/build_kibana_path'; -import { - getRedirectAppPath, - INTERNAL_ROUTES, - PUBLIC_ROUTES, - REPORTING_MANAGEMENT_HOME, -} from '../../../common/constants'; -import { BaseParams, JobId, ManagementLinkFn, ReportApiJSON } from '../../../common/types'; +import { INTERNAL_ROUTES, PUBLIC_ROUTES } from '../../../common/constants'; import { add } from '../../notifier/job_completion_notifications'; import { Job } from '../job'; diff --git a/x-pack/plugins/reporting/public/lib/stream_handler.test.ts b/x-pack/plugins/reporting/public/lib/stream_handler.test.ts index ed3b973a95e64..3c2aef023022b 100644 --- a/x-pack/plugins/reporting/public/lib/stream_handler.test.ts +++ b/x-pack/plugins/reporting/public/lib/stream_handler.test.ts @@ -6,9 +6,12 @@ */ import sinon, { stub } from 'sinon'; + import { NotificationsStart } from '@kbn/core/public'; -import { coreMock, themeServiceMock, docLinksServiceMock } from '@kbn/core/public/mocks'; -import { JobSummary, ReportApiJSON } from '../../common/types'; +import { coreMock, docLinksServiceMock, themeServiceMock } from '@kbn/core/public/mocks'; +import { ReportApiJSON } from '@kbn/reporting-common/types'; + +import { JobSummary } from '../types'; import { Job } from './job'; import { ReportingAPIClient } from './reporting_api_client'; import { ReportingNotifierStreamHandler } from './stream_handler'; diff --git a/x-pack/plugins/reporting/public/lib/stream_handler.ts b/x-pack/plugins/reporting/public/lib/stream_handler.ts index ef27989a6d420..6bdba0b9bf84d 100644 --- a/x-pack/plugins/reporting/public/lib/stream_handler.ts +++ b/x-pack/plugins/reporting/public/lib/stream_handler.ts @@ -5,20 +5,23 @@ * 2.0. */ -import { i18n } from '@kbn/i18n'; import * as Rx from 'rxjs'; import { catchError, map } from 'rxjs/operators'; -import { NotificationsSetup, ThemeServiceStart, DocLinksStart } from '@kbn/core/public'; -import { JOB_COMPLETION_NOTIFICATIONS_SESSION_KEY, JOB_STATUSES } from '../../common/constants'; -import { JobId, JobSummary, JobSummarySet } from '../../common/types'; + +import { DocLinksStart, NotificationsSetup, ThemeServiceStart } from '@kbn/core/public'; +import { i18n } from '@kbn/i18n'; +import { JOB_COMPLETION_NOTIFICATIONS_SESSION_KEY, JOB_STATUS } from '@kbn/reporting-common'; +import { JobId } from '@kbn/reporting-common/types'; + import { getFailureToast, - getWarningToast, - getSuccessToast, getGeneralErrorToast, - getWarningMaxSizeToast, + getSuccessToast, getWarningFormulasToast, + getWarningMaxSizeToast, + getWarningToast, } from '../notifier'; +import { JobSummary, JobSummarySet } from '../types'; import { Job } from './job'; import { ReportingAPIClient } from './reporting_api_client'; @@ -84,7 +87,7 @@ export class ReportingNotifierStreamHandler { ), completedOptions ); - } else if (job.status === JOB_STATUSES.WARNINGS) { + } else if (job.status === JOB_STATUS.WARNINGS) { this.notifications.toasts.addWarning( getWarningToast( job, @@ -141,9 +144,9 @@ export class ReportingNotifierStreamHandler { for (const job of jobs) { const { id: jobId, status: jobStatus } = job; if (storedJobs.includes(jobId)) { - if (jobStatus === JOB_STATUSES.COMPLETED || jobStatus === JOB_STATUSES.WARNINGS) { + if (jobStatus === JOB_STATUS.COMPLETED || jobStatus === JOB_STATUS.WARNINGS) { completedJobs.push(getReportStatus(job)); - } else if (jobStatus === JOB_STATUSES.FAILED) { + } else if (jobStatus === JOB_STATUS.FAILED) { failedJobs.push(getReportStatus(job)); } else { pending.push(jobId); diff --git a/x-pack/plugins/reporting/public/management/components/ilm_policy_link.tsx b/x-pack/plugins/reporting/public/management/components/ilm_policy_link.tsx index 092f33d06215c..8bb72cddd6c76 100644 --- a/x-pack/plugins/reporting/public/management/components/ilm_policy_link.tsx +++ b/x-pack/plugins/reporting/public/management/components/ilm_policy_link.tsx @@ -7,11 +7,12 @@ import type { FunctionComponent } from 'react'; import React from 'react'; + import { i18n } from '@kbn/i18n'; import { EuiButtonEmpty } from '@elastic/eui'; import type { ApplicationStart } from '@kbn/core/public'; +import { ILM_POLICY_NAME } from '@kbn/reporting-common'; -import { ILM_POLICY_NAME } from '../../../common/constants'; import { LocatorPublic, SerializableRecord } from '../../shared_imports'; interface Props { diff --git a/x-pack/plugins/reporting/public/management/components/migrate_ilm_policy_callout/ilm_policy_migration_needed_callout.tsx b/x-pack/plugins/reporting/public/management/components/migrate_ilm_policy_callout/ilm_policy_migration_needed_callout.tsx index a1b0dbcd24c30..4e8d039251e81 100644 --- a/x-pack/plugins/reporting/public/management/components/migrate_ilm_policy_callout/ilm_policy_migration_needed_callout.tsx +++ b/x-pack/plugins/reporting/public/management/components/migrate_ilm_policy_callout/ilm_policy_migration_needed_callout.tsx @@ -5,16 +5,14 @@ * 2.0. */ +import { EuiButton, EuiCallOut, EuiCode } from '@elastic/eui'; +import type { NotificationsSetup } from '@kbn/core/public'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n-react'; +import { ILM_POLICY_NAME } from '@kbn/reporting-common'; import type { FunctionComponent } from 'react'; import React, { useState } from 'react'; import useMountedState from 'react-use/lib/useMountedState'; -import { EuiCallOut, EuiButton, EuiCode } from '@elastic/eui'; - -import type { NotificationsSetup } from '@kbn/core/public'; - -import { ILM_POLICY_NAME } from '../../../../common/constants'; import { useInternalApiClient } from '../../../lib/reporting_api_client'; diff --git a/x-pack/plugins/reporting/public/management/components/report_diagnostic.tsx b/x-pack/plugins/reporting/public/management/components/report_diagnostic.tsx index dd59f34eb24a9..2e63ab4a6f253 100644 --- a/x-pack/plugins/reporting/public/management/components/report_diagnostic.tsx +++ b/x-pack/plugins/reporting/public/management/components/report_diagnostic.tsx @@ -19,8 +19,8 @@ import { EuiText, EuiTitle, } from '@elastic/eui'; +import { ClientConfigType } from '@kbn/reporting-public'; import { ReportingAPIClient, DiagnoseResponse } from '../../lib/reporting_api_client'; -import { ClientConfigType } from '../../plugin'; interface Props { apiClient: ReportingAPIClient; diff --git a/x-pack/plugins/reporting/public/management/components/report_info_flyout_content.tsx b/x-pack/plugins/reporting/public/management/components/report_info_flyout_content.tsx index fa8fe07762791..ca47477133f6f 100644 --- a/x-pack/plugins/reporting/public/management/components/report_info_flyout_content.tsx +++ b/x-pack/plugins/reporting/public/management/components/report_info_flyout_content.tsx @@ -5,24 +5,23 @@ * 2.0. */ +import moment from 'moment'; import React, { FunctionComponent } from 'react'; -import { i18n } from '@kbn/i18n'; + import { + EuiCallOut, EuiDescriptionList, EuiDescriptionListProps, - EuiTitle, - EuiCallOut, EuiSpacer, + EuiTitle, } from '@elastic/eui'; -import moment from 'moment'; -import { VisualReportingSoftDisabledError } from '@kbn/reporting-common'; +import { i18n } from '@kbn/i18n'; +import { VisualReportingSoftDisabledError } from '@kbn/reporting-common/errors'; import { USES_HEADLESS_JOB_TYPES } from '../../../common/constants'; - import type { Job } from '../../lib/job'; -import { useKibana } from '../../shared_imports'; - import { sharedI18nTexts } from '../../shared_i18n_texts'; +import { useKibana } from '../../shared_imports'; // TODO: Move all of these i18n texts to ./i18n_texts.tsx const NA = i18n.translate('xpack.reporting.listing.infoPanel.notApplicableLabel', { diff --git a/x-pack/plugins/reporting/public/management/components/report_status_indicator.tsx b/x-pack/plugins/reporting/public/management/components/report_status_indicator.tsx index 3f15813cd4c2f..08e58d538da3b 100644 --- a/x-pack/plugins/reporting/public/management/components/report_status_indicator.tsx +++ b/x-pack/plugins/reporting/public/management/components/report_status_indicator.tsx @@ -8,9 +8,9 @@ import React, { FC, useMemo } from 'react'; import { i18n } from '@kbn/i18n'; import { EuiFlexGroup, EuiFlexItem, EuiIcon, EuiLoadingSpinner, EuiToolTip } from '@elastic/eui'; +import { JOB_STATUS } from '@kbn/reporting-common/constants'; import type { Job } from '../../lib/job'; -import { JOB_STATUSES } from '../../../common/constants'; import { jobHasIssues } from '../utils'; interface Props { @@ -60,7 +60,7 @@ export const ReportStatusIndicator: FC = ({ job }) => { let statusText: string; switch (job.status) { - case JOB_STATUSES.COMPLETED: + case JOB_STATUS.COMPLETED: if (hasIssues) { icon = ; statusText = i18nTexts.completedWithWarnings; @@ -69,19 +69,19 @@ export const ReportStatusIndicator: FC = ({ job }) => { icon = ; statusText = i18nTexts.completed; break; - case JOB_STATUSES.WARNINGS: + case JOB_STATUS.WARNINGS: icon = ; statusText = i18nTexts.completedWithWarnings; break; - case JOB_STATUSES.PENDING: + case JOB_STATUS.PENDING: icon = ; statusText = i18nTexts.pending; break; - case JOB_STATUSES.PROCESSING: + case JOB_STATUS.PROCESSING: icon = ; statusText = i18nTexts.processing({ attempt: job.attempts, of: job.max_attempts }); break; - case JOB_STATUSES.FAILED: + case JOB_STATUS.FAILED: icon = ; statusText = i18nTexts.failed; break; diff --git a/x-pack/plugins/reporting/public/management/index.ts b/x-pack/plugins/reporting/public/management/index.ts index c3e338af8ad3d..4b9074267dd49 100644 --- a/x-pack/plugins/reporting/public/management/index.ts +++ b/x-pack/plugins/reporting/public/management/index.ts @@ -5,11 +5,11 @@ * 2.0. */ -import { ApplicationStart, ToastsSetup } from '@kbn/core/public'; -import { LicensingPluginStart } from '@kbn/licensing-plugin/public'; -import { UseIlmPolicyStatusReturn } from '../lib/ilm_policy_status_context'; -import { ReportingAPIClient } from '../lib/reporting_api_client'; -import { ClientConfigType } from '../plugin'; +import type { ApplicationStart, ToastsSetup } from '@kbn/core/public'; +import type { LicensingPluginStart } from '@kbn/licensing-plugin/public'; +import type { ClientConfigType } from '@kbn/reporting-public'; +import type { UseIlmPolicyStatusReturn } from '../lib/ilm_policy_status_context'; +import type { ReportingAPIClient } from '../lib/reporting_api_client'; import type { SharePluginSetup } from '../shared_imports'; export interface ListingProps { diff --git a/x-pack/plugins/reporting/public/management/mount_management_section.tsx b/x-pack/plugins/reporting/public/management/mount_management_section.tsx index 4c994a5bb61b4..60cd66d952780 100644 --- a/x-pack/plugins/reporting/public/management/mount_management_section.tsx +++ b/x-pack/plugins/reporting/public/management/mount_management_section.tsx @@ -5,19 +5,20 @@ * 2.0. */ -import { I18nProvider } from '@kbn/i18n-react'; import * as React from 'react'; import { render, unmountComponentAtNode } from 'react-dom'; import { Observable } from 'rxjs'; + import { CoreSetup, CoreStart } from '@kbn/core/public'; +import { I18nProvider } from '@kbn/i18n-react'; import { ILicense } from '@kbn/licensing-plugin/public'; import { KibanaThemeProvider } from '@kbn/react-kibana-context-theme'; -import { ReportingAPIClient, InternalApiClientProvider } from '../lib/reporting_api_client'; +import type { ClientConfigType } from '@kbn/reporting-public'; +import { ReportListing } from '.'; import { IlmPolicyStatusContextProvider } from '../lib/ilm_policy_status_context'; -import { ClientConfigType } from '../plugin'; +import { InternalApiClientProvider, ReportingAPIClient } from '../lib/reporting_api_client'; import type { ManagementAppMountParams, SharePluginSetup } from '../shared_imports'; import { KibanaContextProvider } from '../shared_imports'; -import { ReportListing } from '.'; export async function mountManagementSection( coreSetup: CoreSetup, diff --git a/x-pack/plugins/reporting/public/management/report_listing.test.ts b/x-pack/plugins/reporting/public/management/report_listing.test.ts index 0ec0e47ea5132..d43930cff5af9 100644 --- a/x-pack/plugins/reporting/public/management/report_listing.test.ts +++ b/x-pack/plugins/reporting/public/management/report_listing.test.ts @@ -5,16 +5,15 @@ * 2.0. */ -import type { Observable } from 'rxjs'; import { act } from 'react-dom/test-utils'; +import type { Observable } from 'rxjs'; import type { ILicense } from '@kbn/licensing-plugin/public'; -import type { IlmPolicyMigrationStatus } from '../../common/types'; +import { IlmPolicyMigrationStatus } from '@kbn/reporting-common/types'; import { ListingProps as Props } from '.'; - -import { setup, TestBed, TestDependencies, mockJobs } from './__test__'; import { Job } from '../lib/job'; +import { TestBed, TestDependencies, mockJobs, setup } from './__test__'; import { mockConfig } from './__test__/report_listing.test.helpers'; describe('ReportListing', () => { diff --git a/x-pack/plugins/reporting/public/management/report_listing.tsx b/x-pack/plugins/reporting/public/management/report_listing.tsx index d6289bc2032f9..31976dd196a9a 100644 --- a/x-pack/plugins/reporting/public/management/report_listing.tsx +++ b/x-pack/plugins/reporting/public/management/report_listing.tsx @@ -5,41 +5,44 @@ * 2.0. */ +import { Component, Fragment, default as React } from 'react'; +import { Subscription } from 'rxjs'; + import { EuiBasicTable, + EuiBasicTableColumn, EuiFlexGroup, EuiFlexItem, + EuiIconTip, + EuiLink, EuiLoadingSpinner, EuiPageHeader, EuiSpacer, - EuiBasicTableColumn, - EuiIconTip, - EuiLink, } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n-react'; -import { Component, default as React, Fragment } from 'react'; -import { Subscription } from 'rxjs'; import { ILicense } from '@kbn/licensing-plugin/public'; +import { durationToNumber } from '@kbn/reporting-common'; + +import { ListingProps as Props } from '.'; import { REPORT_TABLE_ID, REPORT_TABLE_ROW_ID } from '../../common/constants'; import { prettyPrintJobType } from '../../common/job_utils'; import { Poller } from '../../common/poller'; -import { durationToNumber } from '../../common/schema_utils'; import { useIlmPolicyStatus } from '../lib/ilm_policy_status_context'; import { Job } from '../lib/job'; import { checkLicense } from '../lib/license_check'; import { useInternalApiClient } from '../lib/reporting_api_client'; import { useKibana } from '../shared_imports'; -import { ListingProps as Props } from '.'; import { IlmPolicyLink, MigrateIlmPolicyCallOut, ReportDeleteButton, ReportDiagnostic, - ReportStatusIndicator, ReportInfoFlyout, + ReportStatusIndicator, } from './components'; import { guessAppIconTypeFromObjectType } from './utils'; + import './report_listing.scss'; type TableColumn = EuiBasicTableColumn; diff --git a/x-pack/plugins/reporting/public/management/utils.ts b/x-pack/plugins/reporting/public/management/utils.ts index 87e49c2054f92..b26c5fdf58046 100644 --- a/x-pack/plugins/reporting/public/management/utils.ts +++ b/x-pack/plugins/reporting/public/management/utils.ts @@ -6,7 +6,7 @@ */ import type { IconType } from '@elastic/eui'; -import { JOB_STATUSES } from '../../common/constants'; +import { JOB_STATUS } from '@kbn/reporting-common'; import { Job } from '../lib/job'; /** @@ -35,6 +35,6 @@ export const guessAppIconTypeFromObjectType = (type: string): IconType => { export const jobHasIssues = (job: Job): boolean => { return ( Boolean(job.getWarnings()) || - [JOB_STATUSES.WARNINGS, JOB_STATUSES.FAILED].some((status) => job.status === status) + [JOB_STATUS.WARNINGS, JOB_STATUS.FAILED].some((status) => job.status === status) ); }; diff --git a/x-pack/plugins/reporting/public/notifier/job_completion_notifications.ts b/x-pack/plugins/reporting/public/notifier/job_completion_notifications.ts index c4addfa3eedef..61db874e75208 100644 --- a/x-pack/plugins/reporting/public/notifier/job_completion_notifications.ts +++ b/x-pack/plugins/reporting/public/notifier/job_completion_notifications.ts @@ -5,9 +5,8 @@ * 2.0. */ -import { JOB_COMPLETION_NOTIFICATIONS_SESSION_KEY } from '../../common/constants'; - -type JobId = string; +import { JOB_COMPLETION_NOTIFICATIONS_SESSION_KEY } from '@kbn/reporting-common'; +import { JobId } from '@kbn/reporting-common/types'; const set = (jobs: string[]) => { sessionStorage.setItem(JOB_COMPLETION_NOTIFICATIONS_SESSION_KEY, JSON.stringify(jobs)); diff --git a/x-pack/plugins/reporting/public/notifier/job_download_button.tsx b/x-pack/plugins/reporting/public/notifier/job_download_button.tsx index 05f92a4ed3610..5b7cd42f78a16 100644 --- a/x-pack/plugins/reporting/public/notifier/job_download_button.tsx +++ b/x-pack/plugins/reporting/public/notifier/job_download_button.tsx @@ -7,8 +7,9 @@ import { EuiButton } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n-react'; +import { JobId } from '@kbn/reporting-common/types'; import React from 'react'; -import { JobId, JobSummary } from '../../common/types'; +import { JobSummary } from '../types'; interface Props { getUrl: (jobId: JobId) => string; diff --git a/x-pack/plugins/reporting/public/notifier/job_failure.tsx b/x-pack/plugins/reporting/public/notifier/job_failure.tsx index b1e318a785b7e..e5c6f06413bdf 100644 --- a/x-pack/plugins/reporting/public/notifier/job_failure.tsx +++ b/x-pack/plugins/reporting/public/notifier/job_failure.tsx @@ -11,8 +11,9 @@ import React from 'react'; import { DocLinksStart, ThemeServiceStart, ToastInput } from '@kbn/core/public'; import { toMountPoint } from '@kbn/kibana-react-plugin/public'; import * as errors from '@kbn/reporting-common/errors'; -import type { JobSummary, ManagementLinkFn } from '../../common/types'; +import { ManagementLinkFn } from '@kbn/reporting-common/types'; import { sharedI18nTexts } from '../shared_i18n_texts'; +import type { JobSummary } from '../types'; export const getFailureToast = ( errorText: string, diff --git a/x-pack/plugins/reporting/public/notifier/job_success.tsx b/x-pack/plugins/reporting/public/notifier/job_success.tsx index 44389e164472a..00b08ed2413d9 100644 --- a/x-pack/plugins/reporting/public/notifier/job_success.tsx +++ b/x-pack/plugins/reporting/public/notifier/job_success.tsx @@ -5,11 +5,12 @@ * 2.0. */ -import { FormattedMessage } from '@kbn/i18n-react'; -import React from 'react'; import { ThemeServiceStart, ToastInput } from '@kbn/core/public'; +import { FormattedMessage } from '@kbn/i18n-react'; import { toMountPoint } from '@kbn/kibana-react-plugin/public'; -import { JobId, JobSummary } from '../../common/types'; +import { JobId } from '@kbn/reporting-common/types'; +import React from 'react'; +import { JobSummary } from '../types'; import { DownloadButton } from './job_download_button'; import { ReportLink } from './report_link'; diff --git a/x-pack/plugins/reporting/public/notifier/job_warning.tsx b/x-pack/plugins/reporting/public/notifier/job_warning.tsx index 9df5bbbc913e2..6751eb76ab073 100644 --- a/x-pack/plugins/reporting/public/notifier/job_warning.tsx +++ b/x-pack/plugins/reporting/public/notifier/job_warning.tsx @@ -5,11 +5,12 @@ * 2.0. */ -import { FormattedMessage } from '@kbn/i18n-react'; -import React from 'react'; import { ThemeServiceStart, ToastInput } from '@kbn/core/public'; +import { FormattedMessage } from '@kbn/i18n-react'; import { toMountPoint } from '@kbn/kibana-react-plugin/public'; -import { JobId, JobSummary } from '../../common/types'; +import { JobId } from '@kbn/reporting-common/types'; +import React from 'react'; +import { JobSummary } from '../types'; import { DownloadButton } from './job_download_button'; import { ReportLink } from './report_link'; diff --git a/x-pack/plugins/reporting/public/notifier/job_warning_formulas.tsx b/x-pack/plugins/reporting/public/notifier/job_warning_formulas.tsx index 314610b9b9f29..4cf9f3f655cc1 100644 --- a/x-pack/plugins/reporting/public/notifier/job_warning_formulas.tsx +++ b/x-pack/plugins/reporting/public/notifier/job_warning_formulas.tsx @@ -5,12 +5,15 @@ * 2.0. */ -import { FormattedMessage } from '@kbn/i18n-react'; import React from 'react'; + import { ThemeServiceStart, ToastInput } from '@kbn/core/public'; +import { FormattedMessage } from '@kbn/i18n-react'; import { toMountPoint } from '@kbn/kibana-react-plugin/public'; -import { JobId, JobSummary } from '../../common/types'; +import { JobId } from '@kbn/reporting-common/types'; import { DownloadButton } from './job_download_button'; + +import { JobSummary } from '../types'; import { ReportLink } from './report_link'; export const getWarningFormulasToast = ( diff --git a/x-pack/plugins/reporting/public/notifier/job_warning_max_size.tsx b/x-pack/plugins/reporting/public/notifier/job_warning_max_size.tsx index 41d97ae4d7f3e..54c7628242067 100644 --- a/x-pack/plugins/reporting/public/notifier/job_warning_max_size.tsx +++ b/x-pack/plugins/reporting/public/notifier/job_warning_max_size.tsx @@ -5,11 +5,12 @@ * 2.0. */ -import { FormattedMessage } from '@kbn/i18n-react'; -import React from 'react'; import { ThemeServiceStart, ToastInput } from '@kbn/core/public'; +import { FormattedMessage } from '@kbn/i18n-react'; import { toMountPoint } from '@kbn/kibana-react-plugin/public'; -import { JobId, JobSummary } from '../../common/types'; +import type { JobId } from '@kbn/reporting-common/types'; +import React from 'react'; +import { JobSummary } from '../types'; import { DownloadButton } from './job_download_button'; import { ReportLink } from './report_link'; diff --git a/x-pack/plugins/reporting/public/panel_actions/get_csv_panel_action.test.ts b/x-pack/plugins/reporting/public/panel_actions/get_csv_panel_action.test.ts index ab5be8a06defd..5bf73525c2dcc 100644 --- a/x-pack/plugins/reporting/public/panel_actions/get_csv_panel_action.test.ts +++ b/x-pack/plugins/reporting/public/panel_actions/get_csv_panel_action.test.ts @@ -15,7 +15,7 @@ import { coreMock } from '@kbn/core/public/mocks'; import { dataPluginMock } from '@kbn/data-plugin/public/mocks'; import { licensingMock } from '@kbn/licensing-plugin/public/mocks'; import { ReportingAPIClient } from '../lib/reporting_api_client'; -import type { ReportingPublicPluginStartDendencies } from '../plugin'; +import type { ReportingPublicPluginStartDependencies } from '../plugin'; import type { ActionContext } from './get_csv_panel_action'; import { ReportingCsvPanelAction } from './get_csv_panel_action'; @@ -26,7 +26,7 @@ describe('GetCsvReportPanelAction', () => { let context: ActionContext; let mockLicenseState: LicenseCheckState; let mockSearchSource: SearchSource; - let mockStartServicesPayload: [CoreStart, ReportingPublicPluginStartDendencies, unknown]; + let mockStartServicesPayload: [CoreStart, ReportingPublicPluginStartDependencies, unknown]; let mockStartServices$: Rx.Observable; const mockLicense$ = () => { @@ -64,7 +64,7 @@ describe('GetCsvReportPanelAction', () => { { data: dataPluginMock.createStartContract(), licensing: { ...licensingMock.createStart(), license$: mockLicense$() }, - } as unknown as ReportingPublicPluginStartDendencies, + } as unknown as ReportingPublicPluginStartDependencies, null, ]; mockStartServices$ = Rx.from(Promise.resolve(mockStartServicesPayload)); diff --git a/x-pack/plugins/reporting/public/panel_actions/get_csv_panel_action.tsx b/x-pack/plugins/reporting/public/panel_actions/get_csv_panel_action.tsx index 497d52b944440..40a231a5220e9 100644 --- a/x-pack/plugins/reporting/public/panel_actions/get_csv_panel_action.tsx +++ b/x-pack/plugins/reporting/public/panel_actions/get_csv_panel_action.tsx @@ -5,21 +5,24 @@ * 2.0. */ -import { i18n } from '@kbn/i18n'; -import * as Rx from 'rxjs'; +import { firstValueFrom, Observable } from 'rxjs'; + import type { CoreSetup, NotificationsSetup } from '@kbn/core/public'; import { CoreStart } from '@kbn/core/public'; import type { ISearchEmbeddable } from '@kbn/discover-plugin/public'; -import type { SavedSearch } from '@kbn/saved-search-plugin/public'; import { loadSharingDataHelpers, SEARCH_EMBEDDABLE_TYPE } from '@kbn/discover-plugin/public'; import type { IEmbeddable } from '@kbn/embeddable-plugin/public'; import { ViewMode } from '@kbn/embeddable-plugin/public'; +import { i18n } from '@kbn/i18n'; +import { CSV_REPORTING_ACTION } from '@kbn/reporting-export-types-csv-common'; +import type { SavedSearch } from '@kbn/saved-search-plugin/public'; import type { UiActionsActionDefinition as ActionDefinition } from '@kbn/ui-actions-plugin/public'; import { IncompatibleActionError } from '@kbn/ui-actions-plugin/public'; -import { CSV_REPORTING_ACTION } from '@kbn/reporting-common'; + import { checkLicense } from '../lib/license_check'; import { ReportingAPIClient } from '../lib/reporting_api_client'; -import type { ReportingPublicPluginStartDendencies } from '../plugin'; +import type { ReportingPublicPluginStartDependencies } from '../plugin'; + function isSavedSearchEmbeddable( embeddable: IEmbeddable | ISearchEmbeddable ): embeddable is ISearchEmbeddable { @@ -33,7 +36,7 @@ export interface ActionContext { interface Params { apiClient: ReportingAPIClient; core: CoreSetup; - startServices$: Rx.Observable<[CoreStart, ReportingPublicPluginStartDendencies, unknown]>; + startServices$: Observable<[CoreStart, ReportingPublicPluginStartDependencies, unknown]>; usesUiCapabilities: boolean; } @@ -69,7 +72,7 @@ export class ReportingCsvPanelAction implements ActionDefinition } public async getSharingData(savedSearch: SavedSearch) { - const [{ uiSettings }, { data }] = await Rx.firstValueFrom(this.startServices$); + const [{ uiSettings }, { data }] = await firstValueFrom(this.startServices$); const { getSharingData } = await loadSharingDataHelpers(); return await getSharingData(savedSearch.searchSource, savedSearch, { uiSettings, data }); } diff --git a/x-pack/plugins/reporting/public/plugin.ts b/x-pack/plugins/reporting/public/plugin.ts index 46e425b54239d..fd315269e32a5 100644 --- a/x-pack/plugins/reporting/public/plugin.ts +++ b/x-pack/plugins/reporting/public/plugin.ts @@ -5,10 +5,9 @@ * 2.0. */ -import { i18n } from '@kbn/i18n'; import * as Rx from 'rxjs'; import { catchError, filter, map, mergeMap, takeUntil } from 'rxjs/operators'; -import type { DataPublicPluginStart } from '@kbn/data-plugin/public'; + import { CoreSetup, CoreStart, @@ -19,18 +18,25 @@ import { PluginInitializerContext, ThemeServiceStart, } from '@kbn/core/public'; -import type { ScreenshotModePluginSetup } from '@kbn/screenshot-mode-plugin/public'; +import type { DataPublicPluginStart } from '@kbn/data-plugin/public'; import { CONTEXT_MENU_TRIGGER } from '@kbn/embeddable-plugin/public'; import type { HomePublicPluginSetup, HomePublicPluginStart } from '@kbn/home-plugin/public'; -import { ManagementSetup, ManagementStart } from '@kbn/management-plugin/public'; +import { i18n } from '@kbn/i18n'; import { LicensingPluginStart } from '@kbn/licensing-plugin/public'; -import { durationToNumber } from '../common/schema_utils'; -import { JobId, JobSummarySet } from '../common/types'; -import { ReportingSetup, ReportingStart } from '.'; +import { ManagementSetup, ManagementStart } from '@kbn/management-plugin/public'; +import { ClientConfigType } from '@kbn/reporting-public'; +import type { ScreenshotModePluginSetup } from '@kbn/screenshot-mode-plugin/public'; + +import { JOB_COMPLETION_NOTIFICATIONS_SESSION_KEY, durationToNumber } from '@kbn/reporting-common'; +import type { JobId } from '@kbn/reporting-common/types'; + +import type { ReportingSetup, ReportingStart } from '.'; import { ReportingAPIClient } from './lib/reporting_api_client'; import { ReportingNotifierStreamHandler as StreamHandler } from './lib/stream_handler'; import { getGeneralErrorToast } from './notifier'; import { ReportingCsvPanelAction } from './panel_actions/get_csv_panel_action'; +import { reportingCsvShareProvider } from './share_context_menu/register_csv_reporting'; +import { reportingScreenshotShareProvider } from './share_context_menu/register_pdf_png_reporting'; import { getSharedComponents } from './shared'; import type { SharePluginSetup, @@ -39,17 +45,7 @@ import type { UiActionsStart, } from './shared_imports'; import { AppNavLinkStatus } from './shared_imports'; -import { reportingCsvShareProvider } from './share_context_menu/register_csv_reporting'; -import { reportingScreenshotShareProvider } from './share_context_menu/register_pdf_png_reporting'; -import { JOB_COMPLETION_NOTIFICATIONS_SESSION_KEY } from '../common/constants'; - -export interface ClientConfigType { - poll: { jobsRefresh: { interval: number; intervalErrorMultiplier: number } }; - roles: { enabled: boolean }; - export_types: { pdf: { enabled: boolean }; png: { enabled: boolean }; csv: { enabled: boolean } }; - statefulSettings: { enabled: boolean }; -} - +import type { JobSummarySet } from './types'; function getStored(): JobId[] { const sessionValue = sessionStorage.getItem(JOB_COMPLETION_NOTIFICATIONS_SESSION_KEY); return sessionValue ? JSON.parse(sessionValue) : []; @@ -73,7 +69,7 @@ function handleError( return Rx.of({ completed: [], failed: [] }); } -export interface ReportingPublicPluginSetupDendencies { +export interface ReportingPublicPluginSetupDependencies { home: HomePublicPluginSetup; management: ManagementSetup; uiActions: UiActionsSetup; @@ -81,7 +77,7 @@ export interface ReportingPublicPluginSetupDendencies { share: SharePluginSetup; } -export interface ReportingPublicPluginStartDendencies { +export interface ReportingPublicPluginStartDependencies { home: HomePublicPluginStart; data: DataPublicPluginStart; management: ManagementStart; @@ -99,8 +95,8 @@ export class ReportingPublicPlugin Plugin< ReportingSetup, ReportingStart, - ReportingPublicPluginSetupDendencies, - ReportingPublicPluginStartDendencies + ReportingPublicPluginSetupDependencies, + ReportingPublicPluginStartDependencies > { private kibanaVersion: string; @@ -146,8 +142,8 @@ export class ReportingPublicPlugin } public setup( - core: CoreSetup, - setupDeps: ReportingPublicPluginSetupDendencies + core: CoreSetup, + setupDeps: ReportingPublicPluginSetupDependencies ) { const { getStartServices, uiSettings } = core; const { home, management, screenshotMode, share, uiActions } = setupDeps; diff --git a/x-pack/plugins/reporting/public/redirect/redirect_app.tsx b/x-pack/plugins/reporting/public/redirect/redirect_app.tsx index c7ce0b8d5b24f..f26fae4e85763 100644 --- a/x-pack/plugins/reporting/public/redirect/redirect_app.tsx +++ b/x-pack/plugins/reporting/public/redirect/redirect_app.tsx @@ -5,18 +5,18 @@ * 2.0. */ -import React, { useEffect, useState } from 'react'; -import type { FunctionComponent } from 'react'; import { parse } from 'query-string'; -import { i18n } from '@kbn/i18n'; +import type { FunctionComponent } from 'react'; +import React, { useEffect, useState } from 'react'; + import { EuiCallOut, EuiCodeBlock } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; import type { ScopedHistory } from '@kbn/core/public'; +import { REPORTING_REDIRECT_LOCATOR_STORE_KEY } from '@kbn/reporting-common'; +import { LocatorParams } from '@kbn/reporting-common/types'; import type { ScreenshotModePluginSetup } from '@kbn/screenshot-mode-plugin/public'; -import { REPORTING_REDIRECT_LOCATOR_STORE_KEY } from '../../common/constants'; -import { LocatorParams } from '../../common/types'; - import { ReportingAPIClient } from '../lib/reporting_api_client'; import type { SharePluginSetup } from '../shared_imports'; diff --git a/x-pack/plugins/reporting/public/share_context_menu/register_csv_reporting.tsx b/x-pack/plugins/reporting/public/share_context_menu/register_csv_reporting.tsx index 363eedfafa170..17f26c6c34e8a 100644 --- a/x-pack/plugins/reporting/public/share_context_menu/register_csv_reporting.tsx +++ b/x-pack/plugins/reporting/public/share_context_menu/register_csv_reporting.tsx @@ -7,11 +7,13 @@ import { i18n } from '@kbn/i18n'; import React from 'react'; + +import { CSV_JOB_TYPE } from '@kbn/reporting-export-types-csv-common'; + import type { SearchSourceFields } from '@kbn/data-plugin/common'; import { ShareContext, ShareMenuProvider } from '@kbn/share-plugin/public'; -import { CSV_JOB_TYPE } from '../../common/constants'; import { checkLicense } from '../lib/license_check'; -import { ExportPanelShareOpts } from '.'; +import type { ExportPanelShareOpts } from '.'; import { ReportingPanelContent } from './reporting_panel_content_lazy'; export const reportingCsvShareProvider = ({ diff --git a/x-pack/plugins/reporting/public/share_context_menu/reporting_panel_content/reporting_panel_content.tsx b/x-pack/plugins/reporting/public/share_context_menu/reporting_panel_content/reporting_panel_content.tsx index 58358d33f5b1f..920f74a4f2bba 100644 --- a/x-pack/plugins/reporting/public/share_context_menu/reporting_panel_content/reporting_panel_content.tsx +++ b/x-pack/plugins/reporting/public/share_context_menu/reporting_panel_content/reporting_panel_content.tsx @@ -5,6 +5,13 @@ * 2.0. */ +import React, { Component, ReactElement } from 'react'; +import url from 'url'; + +import { CSV_REPORT_TYPE } from '@kbn/reporting-export-types-csv-common'; +import { PDF_REPORT_TYPE, PDF_REPORT_TYPE_V2 } from '@kbn/reporting-export-types-pdf-common'; +import { PNG_REPORT_TYPE, PNG_REPORT_TYPE_V2 } from '@kbn/reporting-export-types-png-common'; + import { EuiAccordion, EuiButton, @@ -15,20 +22,12 @@ import { EuiSpacer, EuiText, } from '@elastic/eui'; +import { IUiSettingsClient, ThemeServiceSetup, ToastsSetup } from '@kbn/core/public'; import { i18n } from '@kbn/i18n'; import { FormattedMessage, InjectedIntl, injectI18n } from '@kbn/i18n-react'; -import React, { Component, ReactElement } from 'react'; -import { IUiSettingsClient, ThemeServiceSetup, ToastsSetup } from '@kbn/core/public'; -import url from 'url'; import { toMountPoint } from '@kbn/kibana-react-plugin/public'; -import { - CSV_REPORT_TYPE, - PDF_REPORT_TYPE, - PDF_REPORT_TYPE_V2, - PNG_REPORT_TYPE, - PNG_REPORT_TYPE_V2, -} from '../../../common/constants'; -import { BaseParams } from '../../../common/types'; +import type { BaseParams } from '@kbn/reporting-common/types'; + import { ReportingAPIClient } from '../../lib/reporting_api_client'; import { ErrorUnsavedWorkPanel, ErrorUrlTooLongPanel } from './components'; import { getMaxUrlLength } from './constants'; diff --git a/x-pack/plugins/reporting/public/shared/get_shared_components.tsx b/x-pack/plugins/reporting/public/shared/get_shared_components.tsx index ba6b1c6d1a929..577f0135f137d 100644 --- a/x-pack/plugins/reporting/public/shared/get_shared_components.tsx +++ b/x-pack/plugins/reporting/public/shared/get_shared_components.tsx @@ -7,7 +7,10 @@ import { CoreSetup } from '@kbn/core/public'; import React from 'react'; -import { PDF_REPORT_TYPE, PDF_REPORT_TYPE_V2, PNG_REPORT_TYPE_V2 } from '../../common/constants'; + +import { PDF_REPORT_TYPE, PDF_REPORT_TYPE_V2 } from '@kbn/reporting-export-types-pdf-common'; +import { PNG_REPORT_TYPE_V2 } from '@kbn/reporting-export-types-png-common'; + import { ReportingAPIClient } from '../lib/reporting_api_client'; import { ReportingPanelProps } from '../share_context_menu/reporting_panel_content'; import { ScreenCapturePanelContent } from '../share_context_menu/screen_capture_panel_content_lazy'; diff --git a/x-pack/plugins/reporting/public/types.ts b/x-pack/plugins/reporting/public/types.ts index 3be354bada72e..5b88f2abbf5bd 100644 --- a/x-pack/plugins/reporting/public/types.ts +++ b/x-pack/plugins/reporting/public/types.ts @@ -6,6 +6,24 @@ */ import type { CoreSetup, CoreStart } from '@kbn/core/public'; +import { JOB_STATUS } from '@kbn/reporting-common'; +import type { JobId, ReportOutput, ReportSource, TaskRunResult } from '@kbn/reporting-common/types'; + +/* Notifier Toasts */ +export interface JobSummary { + id: JobId; + status: JOB_STATUS; + jobtype: ReportSource['jobtype']; + title: ReportSource['payload']['title']; + errorCode?: ReportOutput['error_code']; + maxSizeReached: TaskRunResult['max_size_reached']; + csvContainsFormulas: TaskRunResult['csv_contains_formulas']; +} + +export interface JobSummarySet { + completed: JobSummary[]; + failed: JobSummary[]; +} export interface KibanaContext { http: CoreSetup['http']; diff --git a/x-pack/plugins/reporting/server/config/create_config.test.ts b/x-pack/plugins/reporting/server/config/create_config.test.ts index dbb16d050297f..bd65ad245e89d 100644 --- a/x-pack/plugins/reporting/server/config/create_config.test.ts +++ b/x-pack/plugins/reporting/server/config/create_config.test.ts @@ -7,7 +7,7 @@ import type { CoreSetup, HttpServerInfo, Logger } from '@kbn/core/server'; import { coreMock, loggingSystemMock } from '@kbn/core/server/mocks'; -import { createMockConfigSchema } from '../test_helpers'; +import { createMockConfigSchema } from '@kbn/reporting-mocks-server'; import { createConfig } from './create_config'; describe('Reporting server createConfig', () => { diff --git a/x-pack/plugins/reporting/server/config/create_config.ts b/x-pack/plugins/reporting/server/config/create_config.ts index 54cd09a0a9ddd..3841b2920a8eb 100644 --- a/x-pack/plugins/reporting/server/config/create_config.ts +++ b/x-pack/plugins/reporting/server/config/create_config.ts @@ -7,9 +7,10 @@ import crypto from 'crypto'; import ipaddr from 'ipaddr.js'; -import type { CoreSetup, Logger } from '@kbn/core/server'; import { sum } from 'lodash'; -import { ReportingConfigType } from './schema'; + +import type { CoreSetup, Logger } from '@kbn/core/server'; +import type { ReportingConfigType } from '@kbn/reporting-server'; /* * Set up dynamic config defaults diff --git a/x-pack/plugins/reporting/server/config/index.ts b/x-pack/plugins/reporting/server/config/index.ts index 3bb4b79dd6fc8..5965693e37c13 100644 --- a/x-pack/plugins/reporting/server/config/index.ts +++ b/x-pack/plugins/reporting/server/config/index.ts @@ -5,10 +5,11 @@ * 2.0. */ +import { get } from 'lodash'; + import { PluginConfigDescriptor } from '@kbn/core/server'; import { i18n } from '@kbn/i18n'; -import { get } from 'lodash'; -import { ConfigSchema, ReportingConfigType } from './schema'; +import { ConfigSchema, ReportingConfigType } from '@kbn/reporting-server'; export const config: PluginConfigDescriptor = { exposeToBrowser: { poll: true, roles: true, export_types: true, statefulSettings: true }, @@ -71,4 +72,3 @@ export const config: PluginConfigDescriptor = { export { createConfig } from './create_config'; export { registerUiSettings } from './ui_settings'; export { ConfigSchema }; -export type { ReportingConfigType }; diff --git a/x-pack/plugins/reporting/server/config/ui_settings.ts b/x-pack/plugins/reporting/server/config/ui_settings.ts index f6122a814d6f7..cb4a5ca4ec09b 100644 --- a/x-pack/plugins/reporting/server/config/ui_settings.ts +++ b/x-pack/plugins/reporting/server/config/ui_settings.ts @@ -6,10 +6,9 @@ */ import { schema } from '@kbn/config-schema'; -import { i18n } from '@kbn/i18n'; import { CoreSetup, UiSettingsParams } from '@kbn/core/server'; -import { UI_SETTINGS_CUSTOM_PDF_LOGO } from '@kbn/reporting-common'; -import { PLUGIN_ID } from '../../common/constants'; +import { i18n } from '@kbn/i18n'; +import { PLUGIN_ID, UI_SETTINGS_CUSTOM_PDF_LOGO } from '@kbn/reporting-common'; const kbToBase64Length = (kb: number) => Math.floor((kb * 1024 * 8) / 6); const maxLogoSizeInBase64 = kbToBase64Length(200); diff --git a/x-pack/plugins/reporting/server/core.ts b/x-pack/plugins/reporting/server/core.ts index c240d6d165704..c4af9d15f8c4c 100644 --- a/x-pack/plugins/reporting/server/core.ts +++ b/x-pack/plugins/reporting/server/core.ts @@ -5,6 +5,9 @@ * 2.0. */ +import * as Rx from 'rxjs'; +import { map, take } from 'rxjs/operators'; + import type { CoreSetup, DocLinksServiceSetup, @@ -23,12 +26,17 @@ import type { DiscoverServerPluginStart } from '@kbn/discover-plugin/server'; import type { PluginSetupContract as FeaturesPluginSetup } from '@kbn/features-plugin/server'; import type { FieldFormatsStart } from '@kbn/field-formats-plugin/server'; import type { LicensingPluginStart } from '@kbn/licensing-plugin/server'; +import type { ReportingServerInfo } from '@kbn/reporting-common/types'; import { - PdfScreenshotResult, - PngScreenshotResult, - ScreenshotOptions, - ScreenshottingStart, -} from '@kbn/screenshotting-plugin/server'; + CsvSearchSourceExportType, + CsvSearchSourceImmediateExportType, + CsvV2ExportType, +} from '@kbn/reporting-export-types-csv'; +import { PdfExportType, PdfV1ExportType } from '@kbn/reporting-export-types-pdf'; +import { PngExportType } from '@kbn/reporting-export-types-png'; +import type { ReportingConfigType } from '@kbn/reporting-server'; +import { ExportType } from '@kbn/reporting-server'; +import { ScreenshottingStart } from '@kbn/screenshotting-plugin/server'; import type { SecurityPluginSetup, SecurityPluginStart } from '@kbn/security-plugin/server'; import { DEFAULT_SPACE_ID } from '@kbn/spaces-plugin/common'; import type { SpacesPluginSetup } from '@kbn/spaces-plugin/server'; @@ -37,23 +45,14 @@ import type { TaskManagerStartContract, } from '@kbn/task-manager-plugin/server'; import type { UsageCounter } from '@kbn/usage-collection-plugin/server'; -import * as Rx from 'rxjs'; -import { map, switchMap, take } from 'rxjs/operators'; + import type { ReportingSetup } from '.'; -import { REPORTING_REDIRECT_LOCATOR_STORE_KEY } from '../common/constants'; -import { createConfig, ReportingConfigType } from './config'; -import { CsvSearchSourceExportType } from './export_types/csv_searchsource'; -import { CsvV2ExportType } from './export_types/csv_v2'; -import { PdfV1ExportType } from './export_types/printable_pdf'; -import { PdfExportType } from './export_types/printable_pdf_v2'; -import { PngExportType } from './export_types/png_v2'; -import { checkLicense, ExportTypesRegistry } from './lib'; +import { createConfig } from './config'; +import { ExportTypesRegistry, checkLicense } from './lib'; import { reportingEventLoggerFactory } from './lib/event_logger/logger'; import type { IReport, ReportingStore } from './lib/store'; import { ExecuteReportTask, MonitorReportsTask, ReportTaskParams } from './lib/tasks'; -import type { PdfScreenshotOptions, PngScreenshotOptions, ReportingPluginRouter } from './types'; -import { CsvSearchSourceImmediateExportType } from './export_types/csv_searchsource_immediate'; -import { ExportType } from './export_types/common'; +import type { ReportingPluginRouter } from './types'; export interface ReportingInternalSetup { basePath: Pick; @@ -83,18 +82,6 @@ export interface ReportingInternalStart { taskManager: TaskManagerStartContract; } -/** - * @internal - */ -export interface ReportingServerInfo { - port: number; - name: string; - uuid: string; - basePath: string; - protocol: string; - hostname: string; -} - /** * @internal */ @@ -134,7 +121,6 @@ export class ReportingCore { this.getContract = () => ({ usesUiCapabilities: () => config.roles.enabled === false, registerExportTypes: (id) => id, - getScreenshots: config.statefulSettings.enabled ? this.getScreenshots.bind(this) : undefined, getSpaceId: this.getSpaceId.bind(this), }); @@ -171,7 +157,7 @@ export class ReportingCore { this.pluginStartDeps = startDeps; // cache this.exportTypesRegistry.getAll().forEach((et) => { - et.start({ ...startDeps, reporting: this.getContract() }); + et.start({ ...startDeps }); }); const { taskManager } = startDeps; @@ -401,25 +387,6 @@ export class ReportingCore { } } - public getScreenshots(options: PdfScreenshotOptions): Rx.Observable; - public getScreenshots(options: PngScreenshotOptions): Rx.Observable; - public getScreenshots( - options: PngScreenshotOptions | PdfScreenshotOptions - ): Rx.Observable { - return Rx.defer(() => this.getPluginStartDeps()).pipe( - switchMap(({ screenshotting }) => { - return screenshotting!.getScreenshots({ - ...options, - urls: options.urls.map((url) => - typeof url === 'string' - ? url - : [url[0], { [REPORTING_REDIRECT_LOCATOR_STORE_KEY]: url[1] }] - ), - } as ScreenshotOptions); - }) - ); - } - public trackReport(reportId: string) { this.executing.add(reportId); } @@ -447,7 +414,7 @@ export class ReportingCore { this.context ); csvImmediateExport.setup(this.getPluginSetupDeps()); - csvImmediateExport.start({ ...startDeps, reporting: this.getContract() }); + csvImmediateExport.start({ ...startDeps }); return csvImmediateExport; } } diff --git a/x-pack/plugins/reporting/server/deprecations/migrate_existing_indices_ilm_policy.test.ts b/x-pack/plugins/reporting/server/deprecations/migrate_existing_indices_ilm_policy.test.ts index 5dbbb9e9570c1..9f0a10b861adb 100644 --- a/x-pack/plugins/reporting/server/deprecations/migrate_existing_indices_ilm_policy.test.ts +++ b/x-pack/plugins/reporting/server/deprecations/migrate_existing_indices_ilm_policy.test.ts @@ -7,9 +7,10 @@ import type { GetDeprecationsContext } from '@kbn/core/server'; import { elasticsearchServiceMock, savedObjectsClientMock } from '@kbn/core/server/mocks'; +import { createMockConfigSchema } from '@kbn/reporting-mocks-server'; import { ReportingCore } from '../core'; -import { createMockConfigSchema, createMockReportingCore } from '../test_helpers'; +import { createMockReportingCore } from '../test_helpers'; import { getDeprecationsInfo } from './migrate_existing_indices_ilm_policy'; diff --git a/x-pack/plugins/reporting/server/deprecations/migrate_existing_indices_ilm_policy.ts b/x-pack/plugins/reporting/server/deprecations/migrate_existing_indices_ilm_policy.ts index 6f0ddba9ce296..d7c6e1fd9fc2a 100644 --- a/x-pack/plugins/reporting/server/deprecations/migrate_existing_indices_ilm_policy.ts +++ b/x-pack/plugins/reporting/server/deprecations/migrate_existing_indices_ilm_policy.ts @@ -5,9 +5,10 @@ * 2.0. */ -import { i18n } from '@kbn/i18n'; import { DeprecationsDetails, GetDeprecationsContext } from '@kbn/core/server'; -import { INTERNAL_ROUTES, ILM_POLICY_NAME } from '../../common/constants'; +import { i18n } from '@kbn/i18n'; +import { ILM_POLICY_NAME } from '@kbn/reporting-common'; +import { INTERNAL_ROUTES } from '../../common/constants'; import { ReportingCore } from '../core'; import { deprecations } from '../lib/deprecations'; diff --git a/x-pack/plugins/reporting/server/deprecations/reporting_role.test.ts b/x-pack/plugins/reporting/server/deprecations/reporting_role.test.ts index 6655927029056..4f58767e78b06 100644 --- a/x-pack/plugins/reporting/server/deprecations/reporting_role.test.ts +++ b/x-pack/plugins/reporting/server/deprecations/reporting_role.test.ts @@ -7,12 +7,9 @@ import { GetDeprecationsContext, IScopedClusterClient } from '@kbn/core/server'; import { elasticsearchServiceMock } from '@kbn/core/server/mocks'; +import { createMockConfigSchema } from '@kbn/reporting-mocks-server'; import { ReportingCore } from '..'; -import { - createMockConfigSchema, - createMockPluginSetup, - createMockReportingCore, -} from '../test_helpers'; +import { createMockPluginSetup, createMockReportingCore } from '../test_helpers'; import { getDeprecationsInfo } from './reporting_role'; let reportingCore: ReportingCore; diff --git a/x-pack/plugins/reporting/server/export_types/common/index.ts b/x-pack/plugins/reporting/server/export_types/common/index.ts deleted file mode 100644 index b81226b9c6112..0000000000000 --- a/x-pack/plugins/reporting/server/export_types/common/index.ts +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -export { decryptJobHeaders } from './decrypt_job_headers'; -export { getFullUrls } from './get_full_urls'; -export { validateUrls } from './validate_urls'; -export { generatePngObservable } from './generate_png'; -export { getCustomLogo } from './get_custom_logo'; -export { ExportType } from './export_type'; -export type { BaseExportTypeSetupDeps, BaseExportTypeStartDeps } from './export_type'; - -export interface TimeRangeParams { - min?: Date | string | number | null; - max?: Date | string | number | null; -} diff --git a/x-pack/plugins/reporting/server/export_types/png_v2/types.ts b/x-pack/plugins/reporting/server/export_types/png_v2/types.ts deleted file mode 100644 index ae5c80e32894a..0000000000000 --- a/x-pack/plugins/reporting/server/export_types/png_v2/types.ts +++ /dev/null @@ -1,8 +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 type { JobParamsPNGV2, TaskPayloadPNGV2 } from '../../../common/types/export_types/png_v2'; diff --git a/x-pack/plugins/reporting/server/export_types/printable_pdf/types.ts b/x-pack/plugins/reporting/server/export_types/printable_pdf/types.ts deleted file mode 100644 index ebf258f73a41f..0000000000000 --- a/x-pack/plugins/reporting/server/export_types/printable_pdf/types.ts +++ /dev/null @@ -1,11 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -export type { - JobParamsPDFDeprecated, - TaskPayloadPDF, -} from '../../../common/types/export_types/printable_pdf'; diff --git a/x-pack/plugins/reporting/server/index.ts b/x-pack/plugins/reporting/server/index.ts index 1089331ccd110..44fa10396672a 100644 --- a/x-pack/plugins/reporting/server/index.ts +++ b/x-pack/plugins/reporting/server/index.ts @@ -5,9 +5,8 @@ * 2.0. */ -import { PluginInitializerContext } from '@kbn/core/server'; -import { ReportingConfigType } from './config'; -import { ReportingPlugin } from './plugin'; +import type { PluginInitializerContext } from '@kbn/core/server'; +import type { ReportingConfigType } from '@kbn/reporting-server'; export { config } from './config'; @@ -17,8 +16,10 @@ export { config } from './config'; export type { ReportingSetup, ReportingStart } from './types'; // @internal -export const plugin = (initContext: PluginInitializerContext) => - new ReportingPlugin(initContext); +export const plugin = async (initContext: PluginInitializerContext) => { + const { ReportingPlugin } = await import('./plugin'); + return new ReportingPlugin(initContext); +}; // @internal export { ReportingCore } from './core'; diff --git a/x-pack/plugins/reporting/server/lib/check_license.ts b/x-pack/plugins/reporting/server/lib/check_license.ts index 9b603a83597b7..a16c2a260d6ea 100644 --- a/x-pack/plugins/reporting/server/lib/check_license.ts +++ b/x-pack/plugins/reporting/server/lib/check_license.ts @@ -6,7 +6,7 @@ */ import { ILicense } from '@kbn/licensing-plugin/server'; -import { ExportType } from '../export_types/common'; +import { ExportType } from '@kbn/reporting-server'; import { ExportTypesRegistry } from './export_types_registry'; export interface LicenseCheckResult { diff --git a/x-pack/plugins/reporting/server/lib/check_params_version.ts b/x-pack/plugins/reporting/server/lib/check_params_version.ts index b154c839f7fd7..9ab249ced9d6a 100644 --- a/x-pack/plugins/reporting/server/lib/check_params_version.ts +++ b/x-pack/plugins/reporting/server/lib/check_params_version.ts @@ -6,8 +6,8 @@ */ import type { Logger } from '@kbn/core/server'; -import { UNVERSIONED_VERSION } from '../../common/constants'; -import type { BaseParams } from '../../common/types'; +import { UNVERSIONED_VERSION } from '@kbn/reporting-common'; +import type { BaseParams } from '@kbn/reporting-common/types'; export function checkParamsVersion(jobParams: BaseParams, logger: Logger) { if (jobParams.version) { diff --git a/x-pack/plugins/reporting/server/lib/content_stream.ts b/x-pack/plugins/reporting/server/lib/content_stream.ts index 7bf7f1108776e..0be61705d84b5 100644 --- a/x-pack/plugins/reporting/server/lib/content_stream.ts +++ b/x-pack/plugins/reporting/server/lib/content_stream.ts @@ -4,14 +4,16 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ + +import { defaults, get } from 'lodash'; +import { Duplex } from 'stream'; +import { v4 as uuidv4 } from 'uuid'; + import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { ByteSizeValue } from '@kbn/config-schema'; import type { ElasticsearchClient, Logger } from '@kbn/core/server'; -import { defaults, get } from 'lodash'; -import { v4 as uuidv4 } from 'uuid'; -import { Duplex } from 'stream'; +import type { ReportSource } from '@kbn/reporting-common/types'; import type { ReportingCore } from '..'; -import type { ReportSource } from '../../common/types'; /** * @note The Elasticsearch `http.max_content_length` is including the whole POST body. diff --git a/x-pack/plugins/reporting/server/lib/deprecations/check_ilm_migration_status.ts b/x-pack/plugins/reporting/server/lib/deprecations/check_ilm_migration_status.ts index 9f3872dfa6918..aab4c1f0cecf4 100644 --- a/x-pack/plugins/reporting/server/lib/deprecations/check_ilm_migration_status.ts +++ b/x-pack/plugins/reporting/server/lib/deprecations/check_ilm_migration_status.ts @@ -5,8 +5,8 @@ * 2.0. */ -import { ILM_POLICY_NAME } from '../../../common/constants'; -import { IlmPolicyMigrationStatus } from '../../../common/types'; +import { IlmPolicyMigrationStatus } from '@kbn/reporting-common/url'; +import { ILM_POLICY_NAME } from '@kbn/reporting-common'; import { IlmPolicyManager } from '../store/ilm_policy_manager'; import type { DeprecationsDependencies } from './types'; diff --git a/x-pack/plugins/reporting/server/lib/event_logger/logger.test.ts b/x-pack/plugins/reporting/server/lib/event_logger/logger.test.ts index cbff4ed0c1d83..84e625cc3981e 100644 --- a/x-pack/plugins/reporting/server/lib/event_logger/logger.test.ts +++ b/x-pack/plugins/reporting/server/lib/event_logger/logger.test.ts @@ -7,7 +7,8 @@ import { loggingSystemMock } from '@kbn/core/server/mocks'; import { ConcreteTaskInstance } from '@kbn/task-manager-plugin/server'; -import { BasePayload } from '../../types'; +import type { BasePayload } from '@kbn/reporting-common/types'; + import { Report } from '../store'; import { ReportingEventLogger, reportingEventLoggerFactory } from './logger'; diff --git a/x-pack/plugins/reporting/server/lib/event_logger/logger.ts b/x-pack/plugins/reporting/server/lib/event_logger/logger.ts index b28efde88fd18..a1a7d8e2ea1ca 100644 --- a/x-pack/plugins/reporting/server/lib/event_logger/logger.ts +++ b/x-pack/plugins/reporting/server/lib/event_logger/logger.ts @@ -7,8 +7,8 @@ import deepMerge from 'deepmerge'; import type { Logger, LogMeta } from '@kbn/core/server'; -import { TaskRunMetrics } from '@kbn/reporting-common'; -import { PLUGIN_ID } from '../../../common/constants'; +import type { TaskRunMetrics } from '@kbn/reporting-common/types'; +import { PLUGIN_ID } from '@kbn/reporting-common'; import { IReport } from '../store'; import { ActionType } from '.'; import { EcsLogAdapter } from './adapter'; diff --git a/x-pack/plugins/reporting/server/lib/event_logger/types.ts b/x-pack/plugins/reporting/server/lib/event_logger/types.ts index da453e066c2be..8a6725eb33a4d 100644 --- a/x-pack/plugins/reporting/server/lib/event_logger/types.ts +++ b/x-pack/plugins/reporting/server/lib/event_logger/types.ts @@ -6,7 +6,7 @@ */ import { LogMeta } from '@kbn/core/server'; -import { TaskRunMetrics } from '@kbn/reporting-common'; +import type { TaskRunMetrics } from '@kbn/reporting-common/types'; import { ActionType } from '.'; export interface ReportingAction extends LogMeta { diff --git a/x-pack/plugins/reporting/server/lib/export_types_registry.ts b/x-pack/plugins/reporting/server/lib/export_types_registry.ts index 4c93410347bb1..23aa3508dc3f4 100644 --- a/x-pack/plugins/reporting/server/lib/export_types_registry.ts +++ b/x-pack/plugins/reporting/server/lib/export_types_registry.ts @@ -6,7 +6,7 @@ */ import { isString } from 'lodash'; -import { ExportType } from '../export_types/common'; +import { ExportType } from '@kbn/reporting-server'; type GetCallbackFn = (item: ExportType) => boolean; diff --git a/x-pack/plugins/reporting/server/lib/index.ts b/x-pack/plugins/reporting/server/lib/index.ts index be26675f05e88..4c3f29bfa1383 100644 --- a/x-pack/plugins/reporting/server/lib/index.ts +++ b/x-pack/plugins/reporting/server/lib/index.ts @@ -8,9 +8,7 @@ export { checkLicense } from './check_license'; export { checkParamsVersion } from './check_params_version'; export { ContentStream, getContentStream } from './content_stream'; -export { cryptoFactory } from './crypto'; export { ExportTypesRegistry } from './export_types_registry'; export { PassThroughStream } from './passthrough_stream'; -export { statuses } from './statuses'; export { ReportingStore, IlmPolicyManager } from './store'; export { startTrace } from './trace'; diff --git a/x-pack/plugins/reporting/server/lib/statuses.ts b/x-pack/plugins/reporting/server/lib/statuses.ts deleted file mode 100644 index 2c25708078aaf..0000000000000 --- a/x-pack/plugins/reporting/server/lib/statuses.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 { JobStatus } from '../../common/types'; - -export const statuses: Record = { - JOB_STATUS_PENDING: 'pending', - JOB_STATUS_PROCESSING: 'processing', - JOB_STATUS_COMPLETED: 'completed', - JOB_STATUS_WARNINGS: 'completed_with_warnings', - JOB_STATUS_FAILED: 'failed', -}; diff --git a/x-pack/plugins/reporting/server/lib/store/ilm_policy_manager/ilm_policy_manager.ts b/x-pack/plugins/reporting/server/lib/store/ilm_policy_manager/ilm_policy_manager.ts index 48a45be80f716..90bda652898f3 100644 --- a/x-pack/plugins/reporting/server/lib/store/ilm_policy_manager/ilm_policy_manager.ts +++ b/x-pack/plugins/reporting/server/lib/store/ilm_policy_manager/ilm_policy_manager.ts @@ -6,8 +6,7 @@ */ import type { ElasticsearchClient } from '@kbn/core/server'; -import { ILM_POLICY_NAME } from '../../../../common/constants'; - +import { ILM_POLICY_NAME } from '@kbn/reporting-common'; import { reportingIlmPolicy } from './constants'; /** diff --git a/x-pack/plugins/reporting/server/lib/store/index.ts b/x-pack/plugins/reporting/server/lib/store/index.ts index 125c592c8626b..5bc72b339d89e 100644 --- a/x-pack/plugins/reporting/server/lib/store/index.ts +++ b/x-pack/plugins/reporting/server/lib/store/index.ts @@ -5,7 +5,6 @@ * 2.0. */ -export type { ReportDocument } from '../../../common/types'; export { Report } from './report'; export { SavedReport } from './saved_report'; export { ReportingStore } from './store'; diff --git a/x-pack/plugins/reporting/server/lib/store/report.ts b/x-pack/plugins/reporting/server/lib/store/report.ts index 6f23c23e9066a..e4ed610eeecd6 100644 --- a/x-pack/plugins/reporting/server/lib/store/report.ts +++ b/x-pack/plugins/reporting/server/lib/store/report.ts @@ -8,18 +8,16 @@ import { omit } from 'lodash'; import moment from 'moment'; import Puid from 'puid'; -import { JOB_STATUSES } from '../../../common/constants'; + +import { JOB_STATUS } from '@kbn/reporting-common'; import { ReportApiJSON, - ReportDocument, ReportDocumentHead, ReportFields, ReportSource, -} from '../../../common/types'; -import type { ReportTaskParams } from '../tasks'; +} from '@kbn/reporting-common/types'; -export type { ReportDocument }; -export type { ReportApiJSON, ReportSource }; +import type { ReportTaskParams } from '../tasks'; const puid = new Puid(); export const MIGRATION_VERSION = '7.14.0'; @@ -95,7 +93,7 @@ export class Report implements Partial { this.meta = opts.meta || { objectType: 'unknown' }; this.metrics = opts.metrics; - this.status = opts.status || JOB_STATUSES.PENDING; + this.status = opts.status || JOB_STATUS.PENDING; this.output = opts.output || null; this.queue_time_ms = fields?.queue_time_ms; diff --git a/x-pack/plugins/reporting/server/lib/store/saved_report.ts b/x-pack/plugins/reporting/server/lib/store/saved_report.ts index c4d46c167a312..090e87470a07d 100644 --- a/x-pack/plugins/reporting/server/lib/store/saved_report.ts +++ b/x-pack/plugins/reporting/server/lib/store/saved_report.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { ReportDocumentHead, ReportSource } from '../../../common/types'; +import { ReportDocumentHead, ReportSource } from '@kbn/reporting-common/types'; import { Report } from '.'; /* diff --git a/x-pack/plugins/reporting/server/lib/store/store.test.ts b/x-pack/plugins/reporting/server/lib/store/store.test.ts index 64556ef1a2c22..18fea1349373e 100644 --- a/x-pack/plugins/reporting/server/lib/store/store.test.ts +++ b/x-pack/plugins/reporting/server/lib/store/store.test.ts @@ -6,9 +6,12 @@ */ import * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { elasticsearchServiceMock, loggingSystemMock } from '@kbn/core/server/mocks'; +import { JOB_STATUS } from '@kbn/reporting-common'; +import { ReportDocument } from '@kbn/reporting-common/types'; +import { createMockConfigSchema } from '@kbn/reporting-mocks-server'; +import { Report, ReportingStore, SavedReport } from '.'; import { ReportingCore } from '../..'; -import { createMockConfigSchema, createMockReportingCore } from '../../test_helpers'; -import { Report, ReportDocument, ReportingStore, SavedReport } from '.'; +import { createMockReportingCore } from '../../test_helpers'; describe('ReportingStore', () => { const mockLogger = loggingSystemMock.createLogger(); @@ -184,7 +187,7 @@ describe('ReportingStore', () => { created_at: 'some time', created_by: 'some security person', jobtype: 'csv_searchsource', - status: 'pending', + status: JOB_STATUS.PENDING, meta: { testMeta: 'meta' } as any, payload: { testPayload: 'payload' } as any, attempts: 0, @@ -391,7 +394,7 @@ describe('ReportingStore', () => { _primary_term: 10002, jobtype: 'test-report-2', created_by: 'created_by_test_string', - status: 'processing', + status: JOB_STATUS.PROCESSING, process_expiration: '2002', max_attempts: 3, payload: { diff --git a/x-pack/plugins/reporting/server/lib/store/store.ts b/x-pack/plugins/reporting/server/lib/store/store.ts index d4907d43bc490..710a78ffe859a 100644 --- a/x-pack/plugins/reporting/server/lib/store/store.ts +++ b/x-pack/plugins/reporting/server/lib/store/store.ts @@ -7,13 +7,12 @@ import { estypes } from '@elastic/elasticsearch'; import type { ElasticsearchClient, Logger } from '@kbn/core/server'; +import { ILM_POLICY_NAME, JOB_STATUS, REPORTING_SYSTEM_INDEX } from '@kbn/reporting-common'; +import { ReportDocument, ReportOutput, ReportSource } from '@kbn/reporting-common/types'; import moment from 'moment'; -import type { IReport, Report, ReportDocument } from '.'; +import type { IReport, Report } from '.'; import { SavedReport } from '.'; -import { statuses } from '..'; import type { ReportingCore } from '../..'; -import { ILM_POLICY_NAME, REPORTING_SYSTEM_INDEX } from '../../../common/constants'; -import type { JobStatus, ReportOutput, ReportSource } from '../../../common/types'; import type { ReportTaskParams } from '../tasks'; import { IlmPolicyManager } from './ilm_policy_manager'; import { indexTimestamp } from './index_timestamp'; @@ -53,7 +52,7 @@ export interface ReportRecordTimeout { _id: string; _index: string; _source: { - status: JobStatus; + status: JOB_STATUS; process_expiration?: string; }; } @@ -165,7 +164,7 @@ export class ReportingStore { ...sourceDoc({ process_expiration: new Date(0).toISOString(), attempts: 0, - status: statuses.JOB_STATUS_PENDING, + status: JOB_STATUS.PENDING, }), }, }; @@ -283,7 +282,7 @@ export class ReportingStore { ): Promise> { const doc = sourceDoc({ ...processingInfo, - status: statuses.JOB_STATUS_PROCESSING, + status: JOB_STATUS.PROCESSING, }); let body: UpdateResponse; @@ -322,7 +321,7 @@ export class ReportingStore { ): Promise> { const doc = sourceDoc({ ...failedInfo, - status: statuses.JOB_STATUS_FAILED, + status: JOB_STATUS.FAILED, }); let body: UpdateResponse; @@ -353,8 +352,8 @@ export class ReportingStore { const { output } = completedInfo; const status = output && output.warnings && output.warnings.length > 0 - ? statuses.JOB_STATUS_WARNINGS - : statuses.JOB_STATUS_COMPLETED; + ? JOB_STATUS.WARNINGS + : JOB_STATUS.COMPLETED; const doc = sourceDoc({ ...completedInfo, status, @@ -383,7 +382,7 @@ export class ReportingStore { public async prepareReportForRetry(report: SavedReport): Promise> { const doc = sourceDoc({ - status: statuses.JOB_STATUS_PENDING, + status: JOB_STATUS.PENDING, process_expiration: null, }); @@ -420,13 +419,13 @@ export class ReportingStore { bool: { must: [ { range: { process_expiration: { lt: `now` } } }, - { terms: { status: [statuses.JOB_STATUS_PROCESSING] } }, + { terms: { status: [JOB_STATUS.PROCESSING] } }, ], }, }; const oldVersionFilter = { bool: { - must: [{ terms: { status: [statuses.JOB_STATUS_PENDING] } }], + must: [{ terms: { status: [JOB_STATUS.PENDING] } }], must_not: [{ exists: { field: 'migration_version' } }], }, }; diff --git a/x-pack/plugins/reporting/server/lib/tasks/execute_report.test.ts b/x-pack/plugins/reporting/server/lib/tasks/execute_report.test.ts index 314fffd3527b5..90b1daacc9f0c 100644 --- a/x-pack/plugins/reporting/server/lib/tasks/execute_report.test.ts +++ b/x-pack/plugins/reporting/server/lib/tasks/execute_report.test.ts @@ -7,13 +7,14 @@ import { loggingSystemMock } from '@kbn/core/server/mocks'; import { KibanaShuttingDownError } from '@kbn/reporting-common'; +import { createMockConfigSchema } from '@kbn/reporting-mocks-server'; +import type { ExportType, ReportingConfigType } from '@kbn/reporting-server'; import type { RunContext } from '@kbn/task-manager-plugin/server'; import { taskManagerMock } from '@kbn/task-manager-plugin/server/mocks'; + import { ExecuteReportTask } from '.'; import type { ReportingCore } from '../..'; -import type { ReportingConfigType } from '../../config'; -import type { ExportType } from '../../export_types/common'; -import { createMockConfigSchema, createMockReportingCore } from '../../test_helpers'; +import { createMockReportingCore } from '../../test_helpers'; import type { SavedReport } from '../store'; const logger = loggingSystemMock.createLogger(); diff --git a/x-pack/plugins/reporting/server/lib/tasks/execute_report.ts b/x-pack/plugins/reporting/server/lib/tasks/execute_report.ts index 61818fe00ef2b..8bc6ba0f865ec 100644 --- a/x-pack/plugins/reporting/server/lib/tasks/execute_report.ts +++ b/x-pack/plugins/reporting/server/lib/tasks/execute_report.ts @@ -5,36 +5,38 @@ * 2.0. */ -import { UpdateResponse } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; -import type { Logger } from '@kbn/core/server'; import moment from 'moment'; import * as Rx from 'rxjs'; import { timeout } from 'rxjs/operators'; import { Writable } from 'stream'; import { finished } from 'stream/promises'; import { setTimeout } from 'timers/promises'; + +import { UpdateResponse } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import type { Logger } from '@kbn/core/server'; +import { + CancellationToken, + KibanaShuttingDownError, + QueueTimeoutError, + ReportingError, + durationToNumber, + numberToDuration, +} from '@kbn/reporting-common'; +import type { ReportDocument, ReportOutput, TaskRunResult } from '@kbn/reporting-common/types'; +import type { ReportingConfigType } from '@kbn/reporting-server'; import type { RunContext, TaskManagerStartContract, TaskRunCreatorFunction, } from '@kbn/task-manager-plugin/server'; -import { - CancellationToken, - ReportingError, - QueueTimeoutError, - KibanaShuttingDownError, - TaskRunResult, -} from '@kbn/reporting-common'; -import { mapToReportingError } from '../../../common/errors/map_to_reporting_error'; + +import { REPORTING_EXECUTE_TYPE, ReportTaskParams, ReportingTask, ReportingTaskStatus } from '.'; import { ExportTypesRegistry, getContentStream } from '..'; import type { ReportingCore } from '../..'; -import { durationToNumber, numberToDuration } from '../../../common/schema_utils'; -import type { ReportOutput } from '../../../common/types'; -import type { ReportingConfigType } from '../../config'; -import type { ReportDocument, ReportingStore } from '../store'; +import { mapToReportingError } from '../../../common/errors/map_to_reporting_error'; +import type { ReportingStore } from '../store'; import { Report, SavedReport } from '../store'; import type { ReportFailedFields, ReportProcessingFields } from '../store/store'; -import { ReportingTask, ReportingTaskStatus, REPORTING_EXECUTE_TYPE, ReportTaskParams } from '.'; import { errorLogger } from './error_logger'; type CompletedReportOutput = Omit; diff --git a/x-pack/plugins/reporting/server/lib/tasks/index.ts b/x-pack/plugins/reporting/server/lib/tasks/index.ts index f60bcefd73853..54493aee6de58 100644 --- a/x-pack/plugins/reporting/server/lib/tasks/index.ts +++ b/x-pack/plugins/reporting/server/lib/tasks/index.ts @@ -6,8 +6,7 @@ */ import { TaskRunCreatorFunction } from '@kbn/task-manager-plugin/server'; -import { ReportSource } from '../../../common/types'; -import { BasePayload } from '../../types'; +import { BasePayload, ReportSource } from '@kbn/reporting-common/types'; export const REPORTING_EXECUTE_TYPE = 'report:execute'; export const REPORTING_MONITOR_TYPE = 'reports:monitor'; diff --git a/x-pack/plugins/reporting/server/lib/tasks/monitor_report.test.ts b/x-pack/plugins/reporting/server/lib/tasks/monitor_report.test.ts index 7bf6dd7e50678..cf17fd2c65221 100644 --- a/x-pack/plugins/reporting/server/lib/tasks/monitor_report.test.ts +++ b/x-pack/plugins/reporting/server/lib/tasks/monitor_report.test.ts @@ -6,12 +6,13 @@ */ import { loggingSystemMock } from '@kbn/core/server/mocks'; -import { ReportingCore } from '../..'; -import { RunContext } from '@kbn/task-manager-plugin/server'; +import { createMockConfigSchema } from '@kbn/reporting-mocks-server'; +import type { RunContext } from '@kbn/task-manager-plugin/server'; import { taskManagerMock } from '@kbn/task-manager-plugin/server/mocks'; -import { ReportingConfigType } from '../../config'; -import { createMockConfigSchema, createMockReportingCore } from '../../test_helpers'; +import type { ReportingConfigType } from '@kbn/reporting-server'; import { MonitorReportsTask } from '.'; +import type { ReportingCore } from '../..'; +import { createMockReportingCore } from '../../test_helpers'; const logger = loggingSystemMock.createLogger(); diff --git a/x-pack/plugins/reporting/server/lib/tasks/monitor_reports.ts b/x-pack/plugins/reporting/server/lib/tasks/monitor_reports.ts index fa599d225b77d..c42e2f8afa5b2 100644 --- a/x-pack/plugins/reporting/server/lib/tasks/monitor_reports.ts +++ b/x-pack/plugins/reporting/server/lib/tasks/monitor_reports.ts @@ -7,12 +7,14 @@ import type { Logger } from '@kbn/core/server'; import moment from 'moment'; -import { TaskManagerStartContract, TaskRunCreatorFunction } from '@kbn/task-manager-plugin/server'; +import type { + TaskManagerStartContract, + TaskRunCreatorFunction, +} from '@kbn/task-manager-plugin/server'; +import { JOB_STATUS, numberToDuration } from '@kbn/reporting-common'; +import type { ReportingConfigType } from '@kbn/reporting-server'; import { ReportingStore } from '..'; import { ReportingCore } from '../..'; -import { numberToDuration } from '../../../common/schema_utils'; -import { ReportingConfigType } from '../../config'; -import { statuses } from '../statuses'; import { SavedReport } from '../store'; import { ReportingTask, ReportingTaskStatus, REPORTING_MONITOR_TYPE, ReportTaskParams } from '.'; @@ -96,7 +98,7 @@ export class MonitorReportsTask implements ReportingTask { const { _id: jobId, process_expiration: processExpiration, status } = report; const eventLog = this.reporting.getEventLogger(report); - if (![statuses.JOB_STATUS_PENDING, statuses.JOB_STATUS_PROCESSING].includes(status)) { + if (![JOB_STATUS.PENDING, JOB_STATUS.PROCESSING].includes(status)) { const invalidStatusError = new Error( `Invalid job status in the monitoring search result: ${status}` ); // only pending or processing jobs possibility need rescheduling @@ -107,7 +109,7 @@ export class MonitorReportsTask implements ReportingTask { throw invalidStatusError; } - if (status === statuses.JOB_STATUS_PENDING) { + if (status === JOB_STATUS.PENDING) { const migratingJobError = new Error( `${jobId} was scheduled in a previous version and left in [${status}] status. Rescheduling...` ); @@ -115,7 +117,7 @@ export class MonitorReportsTask implements ReportingTask { eventLog.logError(migratingJobError); } - if (status === statuses.JOB_STATUS_PROCESSING) { + if (status === JOB_STATUS.PROCESSING) { const expirationTime = moment(processExpiration); const overdueValue = moment().valueOf() - expirationTime.valueOf(); const overdueExpirationError = new Error( diff --git a/x-pack/plugins/reporting/server/mocks/index.ts b/x-pack/plugins/reporting/server/mocks/index.ts index a6626be6ce791..ea9d448aff167 100644 --- a/x-pack/plugins/reporting/server/mocks/index.ts +++ b/x-pack/plugins/reporting/server/mocks/index.ts @@ -11,7 +11,5 @@ export const reportingMock = { createStart: (): ReportingStart => ({ usesUiCapabilities: () => false, registerExportTypes: () => {}, - getSpaceId: jest.fn(), - getScreenshots: jest.fn(), }), }; diff --git a/x-pack/plugins/reporting/server/plugin.test.ts b/x-pack/plugins/reporting/server/plugin.test.ts index 3e57e3bf3322b..3c4e81af540cd 100644 --- a/x-pack/plugins/reporting/server/plugin.test.ts +++ b/x-pack/plugins/reporting/server/plugin.test.ts @@ -7,21 +7,16 @@ import type { CoreSetup, CoreStart, Logger } from '@kbn/core/server'; import { coreMock, loggingSystemMock } from '@kbn/core/server/mocks'; -import { - CSV_REPORT_TYPE, - CSV_REPORT_TYPE_V2, - PDF_REPORT_TYPE, - PDF_REPORT_TYPE_V2, - PNG_REPORT_TYPE_V2, -} from '../common/constants'; +import { createMockConfigSchema } from '@kbn/reporting-mocks-server'; + +import { CSV_REPORT_TYPE, CSV_REPORT_TYPE_V2 } from '@kbn/reporting-export-types-csv-common'; +import { PDF_REPORT_TYPE, PDF_REPORT_TYPE_V2 } from '@kbn/reporting-export-types-pdf-common'; +import { PNG_REPORT_TYPE_V2 } from '@kbn/reporting-export-types-png-common'; + import type { ReportingCore, ReportingInternalStart } from './core'; import { ExportTypesRegistry } from './lib/export_types_registry'; import { ReportingPlugin } from './plugin'; -import { - createMockConfigSchema, - createMockPluginSetup, - createMockPluginStart, -} from './test_helpers'; +import { createMockPluginSetup, createMockPluginStart } from './test_helpers'; import type { ReportingSetupDeps } from './types'; const sleep = (time: number) => new Promise((r) => setTimeout(r, time)); diff --git a/x-pack/plugins/reporting/server/plugin.ts b/x-pack/plugins/reporting/server/plugin.ts index 3e64a5ddca85e..b05430200c2e1 100644 --- a/x-pack/plugins/reporting/server/plugin.ts +++ b/x-pack/plugins/reporting/server/plugin.ts @@ -12,20 +12,21 @@ import type { Plugin, PluginInitializerContext, } from '@kbn/core/server'; +import { PLUGIN_ID } from '@kbn/reporting-common'; +import type { ReportingConfigType } from '@kbn/reporting-server'; +import { setFieldFormats } from '@kbn/reporting-server'; import { ReportingCore } from '.'; -import { PLUGIN_ID } from '../common/constants'; -import { registerUiSettings, ReportingConfigType } from './config'; +import { registerUiSettings } from './config'; import { registerDeprecations } from './deprecations'; import { ReportingStore } from './lib'; import { registerRoutes } from './routes'; -import { setFieldFormats } from './services'; import type { - ReportingRequestHandlerContext, ReportingSetup, ReportingSetupDeps, ReportingStart, ReportingStartDeps, } from './types'; +import { ReportingRequestHandlerContext } from './types'; import { registerReportingUsageCollector } from './usage'; /* diff --git a/x-pack/plugins/reporting/server/routes/common/authorized_user_pre_routing.test.ts b/x-pack/plugins/reporting/server/routes/common/authorized_user_pre_routing.test.ts index b4c139e6276a4..a10718bf6376f 100644 --- a/x-pack/plugins/reporting/server/routes/common/authorized_user_pre_routing.test.ts +++ b/x-pack/plugins/reporting/server/routes/common/authorized_user_pre_routing.test.ts @@ -7,10 +7,10 @@ import { KibanaRequest, KibanaResponseFactory } from '@kbn/core/server'; import { coreMock, httpServerMock } from '@kbn/core/server/mocks'; +import { createMockConfigSchema } from '@kbn/reporting-mocks-server'; import { ReportingCore } from '../..'; import { ReportingInternalSetup, ReportingInternalStart } from '../../core'; import { - createMockConfigSchema, createMockPluginSetup, createMockPluginStart, createMockReportingCore, diff --git a/x-pack/plugins/reporting/server/routes/common/authorized_user_pre_routing.ts b/x-pack/plugins/reporting/server/routes/common/authorized_user_pre_routing.ts index d4f6e4bf49ab0..ee58d27d55ea0 100644 --- a/x-pack/plugins/reporting/server/routes/common/authorized_user_pre_routing.ts +++ b/x-pack/plugins/reporting/server/routes/common/authorized_user_pre_routing.ts @@ -6,11 +6,12 @@ */ import { RequestHandler, RouteMethod } from '@kbn/core/server'; -import { AuthenticatedUser } from '@kbn/security-plugin/server'; import { i18n } from '@kbn/i18n'; +import { AuthenticatedUser } from '@kbn/security-plugin/server'; + import { ReportingCore } from '../../core'; +import { ReportingRequestHandlerContext } from '../../types'; import { getUser } from './get_user'; -import type { ReportingRequestHandlerContext } from '../../types'; const superuserRole = 'superuser'; diff --git a/x-pack/plugins/reporting/server/routes/common/generate/request_handler.test.ts b/x-pack/plugins/reporting/server/routes/common/generate/request_handler.test.ts index 2ba248b17812f..16d1107da4b56 100644 --- a/x-pack/plugins/reporting/server/routes/common/generate/request_handler.test.ts +++ b/x-pack/plugins/reporting/server/routes/common/generate/request_handler.test.ts @@ -15,21 +15,24 @@ jest.mock( } ); -import { KibanaRequest, KibanaResponseFactory } from '@kbn/core/server'; import rison from '@kbn/rison'; + +import { KibanaRequest, KibanaResponseFactory } from '@kbn/core/server'; import { coreMock, httpServerMock, loggingSystemMock } from '@kbn/core/server/mocks'; +import { JobParamsPDFDeprecated, TaskPayloadPDFV2 } from '@kbn/reporting-export-types-pdf-common'; +import { createMockConfigSchema } from '@kbn/reporting-mocks-server'; + import { ReportingCore } from '../../..'; -import { TaskPayloadPDFV2 } from '../../../../common/types/export_types/printable_pdf_v2'; -import { JobParamsPDFDeprecated } from '../../../export_types/printable_pdf/types'; import { Report, ReportingStore } from '../../../lib/store'; -import { createMockConfigSchema, createMockReportingCore } from '../../../test_helpers'; +import { createMockReportingCore } from '../../../test_helpers'; import { ReportingJobResponse, ReportingRequestHandlerContext, ReportingSetup, } from '../../../types'; import { RequestHandler } from './request_handler'; -jest.mock('../../../lib/crypto', () => ({ + +jest.mock('@kbn/reporting-server/crypto', () => ({ cryptoFactory: () => ({ encrypt: () => `hello mock cypher text`, }), diff --git a/x-pack/plugins/reporting/server/routes/common/generate/request_handler.ts b/x-pack/plugins/reporting/server/routes/common/generate/request_handler.ts index 111e4a20e4fdc..10f368097c686 100644 --- a/x-pack/plugins/reporting/server/routes/common/generate/request_handler.ts +++ b/x-pack/plugins/reporting/server/routes/common/generate/request_handler.ts @@ -6,18 +6,21 @@ */ import Boom from '@hapi/boom'; +import moment from 'moment'; + import { schema, TypeOf } from '@kbn/config-schema'; import type { KibanaRequest, KibanaResponseFactory, Logger } from '@kbn/core/server'; import { i18n } from '@kbn/i18n'; +import type { BaseParams } from '@kbn/reporting-common/types'; +import { cryptoFactory } from '@kbn/reporting-server'; import rison from '@kbn/rison'; -import moment from 'moment'; + import { Counters, getCounters } from '..'; import type { ReportingCore } from '../../..'; import { PUBLIC_ROUTES } from '../../../../common/constants'; -import { checkParamsVersion, cryptoFactory } from '../../../lib'; +import { checkParamsVersion } from '../../../lib'; import { Report } from '../../../lib/store'; import type { - BaseParams, ReportingJobResponse, ReportingRequestHandlerContext, ReportingUser, diff --git a/x-pack/plugins/reporting/server/routes/common/get_counter.ts b/x-pack/plugins/reporting/server/routes/common/get_counter.ts index 2888bebcc5e6b..83603d07e5ce8 100644 --- a/x-pack/plugins/reporting/server/routes/common/get_counter.ts +++ b/x-pack/plugins/reporting/server/routes/common/get_counter.ts @@ -5,8 +5,8 @@ * 2.0. */ +import { API_USAGE_COUNTER_TYPE, API_USAGE_ERROR_TYPE } from '@kbn/reporting-common'; import { UsageCounter } from '@kbn/usage-collection-plugin/server'; -import { API_USAGE_COUNTER_TYPE, API_USAGE_ERROR_TYPE } from '../../../common/constants'; export type Counters = ReturnType; diff --git a/x-pack/plugins/reporting/server/routes/common/jobs/get_document_payload.test.ts b/x-pack/plugins/reporting/server/routes/common/jobs/get_document_payload.test.ts index 8c308de4544a1..cbd5f93425847 100644 --- a/x-pack/plugins/reporting/server/routes/common/jobs/get_document_payload.test.ts +++ b/x-pack/plugins/reporting/server/routes/common/jobs/get_document_payload.test.ts @@ -6,10 +6,15 @@ */ import { Readable } from 'stream'; -import { CSV_JOB_TYPE, PDF_JOB_TYPE, PDF_JOB_TYPE_V2 } from '../../../../common/constants'; -import { ReportApiJSON } from '../../../../common/types'; -import { ContentStream, getContentStream, statuses } from '../../../lib'; -import { createMockConfigSchema, createMockReportingCore } from '../../../test_helpers'; + +import { JOB_STATUS } from '@kbn/reporting-common'; +import { ReportApiJSON } from '@kbn/reporting-common/types'; +import { CSV_JOB_TYPE } from '@kbn/reporting-export-types-csv-common'; +import { PDF_JOB_TYPE, PDF_JOB_TYPE_V2 } from '@kbn/reporting-export-types-pdf-common'; +import { createMockConfigSchema } from '@kbn/reporting-mocks-server'; + +import { ContentStream, getContentStream } from '../../../lib'; +import { createMockReportingCore } from '../../../test_helpers'; import { getDocumentPayloadFactory } from './get_document_payload'; import { jobsQueryFactory } from './jobs_query'; @@ -45,7 +50,7 @@ describe('getDocumentPayload', () => { getDocumentPayload({ id: 'id1', index: '.reporting-12345', - status: statuses.JOB_STATUS_COMPLETED, + status: JOB_STATUS.COMPLETED, jobtype: PDF_JOB_TYPE, output: { content_type: 'application/pdf', @@ -71,7 +76,7 @@ describe('getDocumentPayload', () => { getDocumentPayload({ id: 'id1', index: '.reporting-12345', - status: statuses.JOB_STATUS_WARNINGS, + status: JOB_STATUS.WARNINGS, jobtype: CSV_JOB_TYPE, output: { content_type: 'text/csv', @@ -103,7 +108,7 @@ describe('getDocumentPayload', () => { getDocumentPayload({ id: 'id1', index: '.reporting-12345', - status: statuses.JOB_STATUS_FAILED, + status: JOB_STATUS.FAILED, jobtype: PDF_JOB_TYPE_V2, output: {}, payload: {}, @@ -127,7 +132,7 @@ describe('getDocumentPayload', () => { getDocumentPayload({ id: 'id1', index: '.reporting-12345', - status: statuses.JOB_STATUS_PENDING, + status: JOB_STATUS.PENDING, jobtype: PDF_JOB_TYPE_V2, output: {}, payload: {}, diff --git a/x-pack/plugins/reporting/server/routes/common/jobs/get_document_payload.ts b/x-pack/plugins/reporting/server/routes/common/jobs/get_document_payload.ts index 92fac37bb26f2..d8a0027c42d64 100644 --- a/x-pack/plugins/reporting/server/routes/common/jobs/get_document_payload.ts +++ b/x-pack/plugins/reporting/server/routes/common/jobs/get_document_payload.ts @@ -5,13 +5,16 @@ * 2.0. */ -import { ResponseHeaders } from '@kbn/core-http-server'; import { Stream } from 'stream'; + +import { ResponseHeaders } from '@kbn/core-http-server'; +import { ReportApiJSON } from '@kbn/reporting-common/types'; +import { CSV_JOB_TYPE, CSV_JOB_TYPE_DEPRECATED } from '@kbn/reporting-export-types-csv-common'; +import { JOB_STATUS } from '@kbn/reporting-common'; +import { ExportType } from '@kbn/reporting-server'; + import { ReportingCore } from '../../..'; -import { CSV_JOB_TYPE, CSV_JOB_TYPE_DEPRECATED } from '../../../../common/constants'; -import { ReportApiJSON } from '../../../../common/types'; -import { ExportType } from '../../../export_types/common'; -import { getContentStream, statuses } from '../../../lib'; +import { getContentStream } from '../../../lib'; import { jobsQueryFactory } from './jobs_query'; export interface ErrorFromPayload { @@ -106,11 +109,11 @@ export function getDocumentPayloadFactory(reporting: ReportingCore) { return async function getDocumentPayload(report: ReportApiJSON): Promise { if (report.output) { - if ([statuses.JOB_STATUS_COMPLETED, statuses.JOB_STATUS_WARNINGS].includes(report.status)) { + if ([JOB_STATUS.COMPLETED, JOB_STATUS.WARNINGS].includes(report.status)) { return getCompleted(report as Required); } - if (statuses.JOB_STATUS_FAILED === report.status) { + if (JOB_STATUS.FAILED === report.status) { return getFailure(report); } } diff --git a/x-pack/plugins/reporting/server/routes/common/jobs/get_job_routes.ts b/x-pack/plugins/reporting/server/routes/common/jobs/get_job_routes.ts index c0d29849e94f3..ddd226187adf0 100644 --- a/x-pack/plugins/reporting/server/routes/common/jobs/get_job_routes.ts +++ b/x-pack/plugins/reporting/server/routes/common/jobs/get_job_routes.ts @@ -5,17 +5,19 @@ * 2.0. */ +import { promisify } from 'util'; + import { schema, TypeOf } from '@kbn/config-schema'; import { KibanaRequest, KibanaResponseFactory } from '@kbn/core-http-server'; -import { promisify } from 'util'; +import { ALLOWED_JOB_CONTENT_TYPES } from '@kbn/reporting-common'; + import { getCounters } from '..'; import { ReportingCore } from '../../..'; -import { ALLOWED_JOB_CONTENT_TYPES } from '../../../../common/constants'; import { getContentStream } from '../../../lib'; import { ReportingRequestHandlerContext, ReportingUser } from '../../../types'; import { handleUnavailable } from '../generate'; -import { jobsQueryFactory } from './jobs_query'; import { jobManagementPreRouting } from './job_management_pre_routing'; +import { jobsQueryFactory } from './jobs_query'; const validate = { params: schema.object({ diff --git a/x-pack/plugins/reporting/server/routes/common/jobs/job_management_pre_routing.test.ts b/x-pack/plugins/reporting/server/routes/common/jobs/job_management_pre_routing.test.ts index 3d4a182d0d743..ce0f6b5697eed 100644 --- a/x-pack/plugins/reporting/server/routes/common/jobs/job_management_pre_routing.test.ts +++ b/x-pack/plugins/reporting/server/routes/common/jobs/job_management_pre_routing.test.ts @@ -6,10 +6,10 @@ */ import { httpServerMock } from '@kbn/core/server/mocks'; +import { createMockConfigSchema } from '@kbn/reporting-mocks-server'; import { ReportingCore } from '../../..'; import { ReportingInternalSetup, ReportingInternalStart } from '../../../core'; import { - createMockConfigSchema, createMockPluginSetup, createMockPluginStart, createMockReportingCore, diff --git a/x-pack/plugins/reporting/server/routes/common/jobs/job_management_pre_routing.ts b/x-pack/plugins/reporting/server/routes/common/jobs/job_management_pre_routing.ts index 79221c0c49d34..cfe9df9cebc40 100644 --- a/x-pack/plugins/reporting/server/routes/common/jobs/job_management_pre_routing.ts +++ b/x-pack/plugins/reporting/server/routes/common/jobs/job_management_pre_routing.ts @@ -6,11 +6,12 @@ */ import Boom from '@hapi/boom'; + import { IKibanaResponse, kibanaResponseFactory } from '@kbn/core/server'; +import { ReportApiJSON } from '@kbn/reporting-common/types'; import { i18n } from '@kbn/i18n'; import { Counters } from '..'; import { ReportingCore } from '../../..'; -import { ReportApiJSON } from '../../../lib/store/report'; import { ReportingUser } from '../../../types'; import { jobsQueryFactory } from './jobs_query'; diff --git a/x-pack/plugins/reporting/server/routes/common/jobs/jobs_query.test.ts b/x-pack/plugins/reporting/server/routes/common/jobs/jobs_query.test.ts index f0c656da2050a..616079c0aa27e 100644 --- a/x-pack/plugins/reporting/server/routes/common/jobs/jobs_query.test.ts +++ b/x-pack/plugins/reporting/server/routes/common/jobs/jobs_query.test.ts @@ -5,11 +5,13 @@ * 2.0. */ +import { set } from '@kbn/safer-lodash-set'; + import { ElasticsearchClient } from '@kbn/core/server'; import { elasticsearchServiceMock } from '@kbn/core/server/mocks'; -import { set } from '@kbn/safer-lodash-set'; -import { statuses } from '../../../lib'; -import { createMockConfigSchema, createMockReportingCore } from '../../../test_helpers'; +import { JOB_STATUS } from '@kbn/reporting-common'; +import { createMockConfigSchema } from '@kbn/reporting-mocks-server'; +import { createMockReportingCore } from '../../../test_helpers'; import { jobsQueryFactory } from './jobs_query'; describe('jobsQuery', () => { @@ -184,7 +186,7 @@ describe('jobsQuery', () => { _id: 'id1', jobtype: 'pdf', output: { content: 'Some error' }, - status: statuses.JOB_STATUS_FAILED, + status: JOB_STATUS.FAILED, }, }, ]) @@ -218,7 +220,7 @@ describe('jobsQuery', () => { _source: { _id: 'id1', jobtype: 'pdf', - status: statuses.JOB_STATUS_PENDING, + status: JOB_STATUS.PENDING, }, }, ]) diff --git a/x-pack/plugins/reporting/server/routes/common/jobs/jobs_query.ts b/x-pack/plugins/reporting/server/routes/common/jobs/jobs_query.ts index 87bf38648bd2f..9efe74a0c3aac 100644 --- a/x-pack/plugins/reporting/server/routes/common/jobs/jobs_query.ts +++ b/x-pack/plugins/reporting/server/routes/common/jobs/jobs_query.ts @@ -5,13 +5,12 @@ * 2.0. */ -import { estypes, errors, TransportResult } from '@elastic/elasticsearch'; +import { TransportResult, errors, estypes } from '@elastic/elasticsearch'; import type { ElasticsearchClient } from '@kbn/core/server'; import { i18n } from '@kbn/i18n'; +import { JOB_STATUS, REPORTING_SYSTEM_INDEX } from '@kbn/reporting-common'; +import { ReportApiJSON, ReportSource } from '@kbn/reporting-common/types'; import type { ReportingCore } from '../../..'; -import { REPORTING_SYSTEM_INDEX } from '../../../../common/constants'; -import type { ReportApiJSON, ReportSource } from '../../../../common/types'; -import { statuses } from '../../../lib/statuses'; import { Report } from '../../../lib/store'; import { runtimeFieldKeys, runtimeFields } from '../../../lib/store/runtime_fields'; import type { ReportingUser } from '../../../types'; @@ -192,7 +191,7 @@ export function jobsQueryFactory(reportingCore: ReportingCore): JobsQueryFactory const hits = response?.hits?.hits?.[0]; const status = hits?._source?.status; - if (status !== statuses.JOB_STATUS_FAILED) { + if (status !== JOB_STATUS.FAILED) { throw new Error(`Can not get error for ${id}`); } diff --git a/x-pack/plugins/reporting/server/routes/internal/deprecations/deprecations.ts b/x-pack/plugins/reporting/server/routes/internal/deprecations/deprecations.ts index 04ff2474674d1..d6322f2d60346 100644 --- a/x-pack/plugins/reporting/server/routes/internal/deprecations/deprecations.ts +++ b/x-pack/plugins/reporting/server/routes/internal/deprecations/deprecations.ts @@ -6,8 +6,9 @@ */ import { errors } from '@elastic/elasticsearch'; import type { Logger, RequestHandler } from '@kbn/core/server'; -import { ILM_POLICY_NAME, INTERNAL_ROUTES } from '../../../../common/constants'; -import type { IlmPolicyStatusResponse } from '../../../../common/types'; +import { ILM_POLICY_NAME } from '@kbn/reporting-common'; +import type { IlmPolicyStatusResponse } from '@kbn/reporting-common/url'; +import { INTERNAL_ROUTES } from '../../../../common/constants'; import type { ReportingCore } from '../../../core'; import { IlmPolicyManager } from '../../../lib'; import { deprecations } from '../../../lib/deprecations'; diff --git a/x-pack/plugins/reporting/server/routes/internal/deprecations/integration_tests/deprecations.test.ts b/x-pack/plugins/reporting/server/routes/internal/deprecations/integration_tests/deprecations.test.ts index 8b82e2bef151f..e143216447af0 100644 --- a/x-pack/plugins/reporting/server/routes/internal/deprecations/integration_tests/deprecations.test.ts +++ b/x-pack/plugins/reporting/server/routes/internal/deprecations/integration_tests/deprecations.test.ts @@ -8,11 +8,11 @@ import { setupServer } from '@kbn/core-test-helpers-test-utils'; import { loggingSystemMock } from '@kbn/core/server/mocks'; import { licensingMock } from '@kbn/licensing-plugin/server/mocks'; +import { createMockConfigSchema } from '@kbn/reporting-mocks-server'; import { securityMock } from '@kbn/security-plugin/server/mocks'; import supertest from 'supertest'; import { INTERNAL_ROUTES } from '../../../../../common/constants'; import { - createMockConfigSchema, createMockPluginSetup, createMockPluginStart, createMockReportingCore, diff --git a/x-pack/plugins/reporting/server/routes/internal/diagnostic/integration_tests/browser.test.ts b/x-pack/plugins/reporting/server/routes/internal/diagnostic/integration_tests/browser.test.ts index be23298a0f0e1..a395fab20e8d3 100644 --- a/x-pack/plugins/reporting/server/routes/internal/diagnostic/integration_tests/browser.test.ts +++ b/x-pack/plugins/reporting/server/routes/internal/diagnostic/integration_tests/browser.test.ts @@ -5,21 +5,19 @@ * 2.0. */ +import * as Rx from 'rxjs'; +import supertest from 'supertest'; + import { setupServer } from '@kbn/core-test-helpers-test-utils'; import { docLinksServiceMock, loggingSystemMock } from '@kbn/core/server/mocks'; -import type { ScreenshottingStart } from '@kbn/screenshotting-plugin/server'; +import { ScreenshottingStart } from '@kbn/screenshotting-plugin/server'; +import { createMockConfigSchema } from '@kbn/reporting-mocks-server'; import { IUsageCounter } from '@kbn/usage-collection-plugin/server/usage_counters/usage_counter'; -import * as Rx from 'rxjs'; -import supertest from 'supertest'; import { ReportingCore } from '../../../..'; import { INTERNAL_ROUTES } from '../../../../../common/constants'; import { reportingMock } from '../../../../mocks'; -import { - createMockConfigSchema, - createMockPluginSetup, - createMockReportingCore, -} from '../../../../test_helpers'; -import type { ReportingRequestHandlerContext } from '../../../../types'; +import { createMockPluginSetup, createMockReportingCore } from '../../../../test_helpers'; +import { ReportingRequestHandlerContext } from '../../../../types'; import { registerDiagnoseBrowser } from '../browser'; type SetupServerReturn = Awaited>; diff --git a/x-pack/plugins/reporting/server/routes/internal/generate/csv_searchsource_immediate.ts b/x-pack/plugins/reporting/server/routes/internal/generate/csv_searchsource_immediate.ts index 90fc2d01dba66..60e8da242ddbf 100644 --- a/x-pack/plugins/reporting/server/routes/internal/generate/csv_searchsource_immediate.ts +++ b/x-pack/plugins/reporting/server/routes/internal/generate/csv_searchsource_immediate.ts @@ -6,12 +6,16 @@ */ import Boom from '@hapi/boom'; +import moment from 'moment'; + import { schema } from '@kbn/config-schema'; import type { KibanaRequest, Logger } from '@kbn/core/server'; -import moment from 'moment'; +import { + CSV_SEARCHSOURCE_IMMEDIATE_TYPE, + JobParamsDownloadCSV, +} from '@kbn/reporting-export-types-csv-common'; import type { ReportingCore } from '../../..'; -import { CSV_SEARCHSOURCE_IMMEDIATE_TYPE, INTERNAL_ROUTES } from '../../../../common/constants'; -import type { JobParamsDownloadCSV } from '../../../export_types/csv_searchsource_immediate/types'; +import { INTERNAL_ROUTES } from '../../../../common/constants'; import { PassThroughStream } from '../../../lib'; import { authorizedUserPreRouting, getCounters } from '../../common'; diff --git a/x-pack/plugins/reporting/server/routes/internal/generate/integration_tests/generation_from_jobparams.test.ts b/x-pack/plugins/reporting/server/routes/internal/generate/integration_tests/generation_from_jobparams.test.ts index c36385ab5174f..be416eab955ba 100644 --- a/x-pack/plugins/reporting/server/routes/internal/generate/integration_tests/generation_from_jobparams.test.ts +++ b/x-pack/plugins/reporting/server/routes/internal/generate/integration_tests/generation_from_jobparams.test.ts @@ -5,27 +5,29 @@ * 2.0. */ +import { BehaviorSubject } from 'rxjs'; +import supertest from 'supertest'; +import rison from '@kbn/rison'; + import { setupServer } from '@kbn/core-test-helpers-test-utils'; import { coreMock, loggingSystemMock } from '@kbn/core/server/mocks'; import { licensingMock } from '@kbn/licensing-plugin/server/mocks'; -import rison from '@kbn/rison'; +import { PdfExportType } from '@kbn/reporting-export-types-pdf'; +import { createMockConfigSchema } from '@kbn/reporting-mocks-server'; import { IUsageCounter } from '@kbn/usage-collection-plugin/server/usage_counters/usage_counter'; -import { BehaviorSubject } from 'rxjs'; -import supertest from 'supertest'; + import { ReportingCore } from '../../../..'; import { INTERNAL_ROUTES } from '../../../../../common/constants'; -import { PdfExportType } from '../../../../export_types/printable_pdf_v2'; import { ReportingStore } from '../../../../lib'; import { ExportTypesRegistry } from '../../../../lib/export_types_registry'; import { Report } from '../../../../lib/store'; import { reportingMock } from '../../../../mocks'; import { - createMockConfigSchema, createMockPluginSetup, createMockPluginStart, createMockReportingCore, } from '../../../../test_helpers'; -import type { ReportingRequestHandlerContext } from '../../../../types'; +import { ReportingRequestHandlerContext } from '../../../../types'; import { registerGenerationRoutesInternal } from '../generate_from_jobparams'; type SetupServerReturn = Awaited>; diff --git a/x-pack/plugins/reporting/server/routes/internal/management/integration_tests/jobs.test.ts b/x-pack/plugins/reporting/server/routes/internal/management/integration_tests/jobs.test.ts index d77a3840cfac3..decc2300026e3 100644 --- a/x-pack/plugins/reporting/server/routes/internal/management/integration_tests/jobs.test.ts +++ b/x-pack/plugins/reporting/server/routes/internal/management/integration_tests/jobs.test.ts @@ -5,25 +5,28 @@ * 2.0. */ +import { BehaviorSubject } from 'rxjs'; +import { Readable } from 'stream'; +import supertest from 'supertest'; + jest.mock('../../../../lib/content_stream', () => ({ getContentStream: jest.fn(), })); + import { estypes } from '@elastic/elasticsearch'; import { setupServer } from '@kbn/core-test-helpers-test-utils'; -import type { ElasticsearchClientMock } from '@kbn/core/server/mocks'; +import { ElasticsearchClientMock } from '@kbn/core/server/mocks'; import { licensingMock } from '@kbn/licensing-plugin/server/mocks'; +import { ExportType } from '@kbn/reporting-server'; +import { createMockConfigSchema } from '@kbn/reporting-mocks-server'; import { IUsageCounter } from '@kbn/usage-collection-plugin/server/usage_counters/usage_counter'; -import { BehaviorSubject } from 'rxjs'; -import { Readable } from 'stream'; -import supertest from 'supertest'; + import { ReportingCore } from '../../../..'; import { INTERNAL_ROUTES } from '../../../../../common/constants'; import { ReportingInternalSetup, ReportingInternalStart } from '../../../../core'; -import { ExportType } from '../../../../export_types/common'; import { ContentStream, ExportTypesRegistry, getContentStream } from '../../../../lib'; import { reportingMock } from '../../../../mocks'; import { - createMockConfigSchema, createMockPluginSetup, createMockPluginStart, createMockReportingCore, diff --git a/x-pack/plugins/reporting/server/routes/public/integration_tests/generation_from_jobparams.test.ts b/x-pack/plugins/reporting/server/routes/public/integration_tests/generation_from_jobparams.test.ts index 18883564030d1..b534583da02c5 100644 --- a/x-pack/plugins/reporting/server/routes/public/integration_tests/generation_from_jobparams.test.ts +++ b/x-pack/plugins/reporting/server/routes/public/integration_tests/generation_from_jobparams.test.ts @@ -5,27 +5,28 @@ * 2.0. */ +import rison from '@kbn/rison'; +import { BehaviorSubject } from 'rxjs'; +import supertest from 'supertest'; + import { setupServer } from '@kbn/core-test-helpers-test-utils'; import { coreMock, loggingSystemMock } from '@kbn/core/server/mocks'; import { licensingMock } from '@kbn/licensing-plugin/server/mocks'; -import rison from '@kbn/rison'; +import { PdfExportType } from '@kbn/reporting-export-types-pdf'; import { IUsageCounter } from '@kbn/usage-collection-plugin/server/usage_counters/usage_counter'; -import { BehaviorSubject } from 'rxjs'; -import supertest from 'supertest'; +import { createMockConfigSchema } from '@kbn/reporting-mocks-server'; import { ReportingCore } from '../../..'; import { PUBLIC_ROUTES } from '../../../../common/constants'; -import { PdfExportType } from '../../../export_types/printable_pdf_v2'; import { ReportingStore } from '../../../lib'; import { ExportTypesRegistry } from '../../../lib/export_types_registry'; import { Report } from '../../../lib/store'; import { reportingMock } from '../../../mocks'; import { - createMockConfigSchema, createMockPluginSetup, createMockPluginStart, createMockReportingCore, } from '../../../test_helpers'; -import type { ReportingRequestHandlerContext } from '../../../types'; +import { ReportingRequestHandlerContext } from '../../../types'; import { registerGenerationRoutesPublic } from '../generate_from_jobparams'; type SetupServerReturn = Awaited>; diff --git a/x-pack/plugins/reporting/server/routes/public/integration_tests/jobs.test.ts b/x-pack/plugins/reporting/server/routes/public/integration_tests/jobs.test.ts index b268d8c089d57..b301b1546dabf 100644 --- a/x-pack/plugins/reporting/server/routes/public/integration_tests/jobs.test.ts +++ b/x-pack/plugins/reporting/server/routes/public/integration_tests/jobs.test.ts @@ -8,22 +8,25 @@ jest.mock('../../../lib/content_stream', () => ({ getContentStream: jest.fn(), })); + +import { BehaviorSubject } from 'rxjs'; +import { Readable } from 'stream'; +import supertest from 'supertest'; + import { estypes } from '@elastic/elasticsearch'; import { setupServer } from '@kbn/core-test-helpers-test-utils'; import type { ElasticsearchClientMock } from '@kbn/core/server/mocks'; import { licensingMock } from '@kbn/licensing-plugin/server/mocks'; +import type { ExportType } from '@kbn/reporting-server'; +import { createMockConfigSchema } from '@kbn/reporting-mocks-server'; import { IUsageCounter } from '@kbn/usage-collection-plugin/server/usage_counters/usage_counter'; -import { BehaviorSubject } from 'rxjs'; -import { Readable } from 'stream'; -import supertest from 'supertest'; + import { ReportingCore } from '../../..'; import { PUBLIC_ROUTES } from '../../../../common/constants'; import { ReportingInternalSetup, ReportingInternalStart } from '../../../core'; -import { ExportType } from '../../../export_types/common'; import { ContentStream, ExportTypesRegistry, getContentStream } from '../../../lib'; import { reportingMock } from '../../../mocks'; import { - createMockConfigSchema, createMockPluginSetup, createMockPluginStart, createMockReportingCore, diff --git a/x-pack/plugins/reporting/server/test_helpers/create_mock_reportingplugin.ts b/x-pack/plugins/reporting/server/test_helpers/create_mock_reportingplugin.ts index d96a66bc9b9fd..eb308d9cf0e15 100644 --- a/x-pack/plugins/reporting/server/test_helpers/create_mock_reportingplugin.ts +++ b/x-pack/plugins/reporting/server/test_helpers/create_mock_reportingplugin.ts @@ -8,6 +8,8 @@ jest.mock('../routes'); jest.mock('../usage'); +import { BehaviorSubject } from 'rxjs'; + import { coreMock, docLinksServiceMock, @@ -21,16 +23,16 @@ import { featuresPluginMock } from '@kbn/features-plugin/server/mocks'; import { FieldFormatsRegistry } from '@kbn/field-formats-plugin/common'; import { fieldFormatsMock } from '@kbn/field-formats-plugin/common/mocks'; import { licensingMock } from '@kbn/licensing-plugin/server/mocks'; +import { createMockConfigSchema } from '@kbn/reporting-mocks-server'; +import type { ReportingConfigType } from '@kbn/reporting-server'; +import { setFieldFormats } from '@kbn/reporting-server'; import { createMockScreenshottingStart } from '@kbn/screenshotting-plugin/server/mock'; import { securityMock } from '@kbn/security-plugin/server/mocks'; import { taskManagerMock } from '@kbn/task-manager-plugin/server/mocks'; -import { BehaviorSubject } from 'rxjs'; -import { DeepPartial } from 'utility-types'; import { ReportingCore } from '..'; -import { ReportingConfigType } from '../config'; + import { ReportingInternalSetup, ReportingInternalStart } from '../core'; import { ReportingStore } from '../lib'; -import { setFieldFormats } from '../services'; export const createMockPluginSetup = ( setupMock: Partial> @@ -83,44 +85,6 @@ export const createMockPluginStart = async ( }; }; -export const createMockConfigSchema = ( - overrides: DeepPartial = {} -): ReportingConfigType => { - // deeply merge the defaults and the provided partial schema - return { - index: '.reporting', - encryptionKey: 'cool-encryption-key-where-did-you-find-it', - ...overrides, - kibanaServer: { - hostname: 'localhost', - ...overrides.kibanaServer, - }, - queue: { - indexInterval: 'week', - pollEnabled: true, - pollInterval: 3000, - timeout: 120000, - ...overrides.queue, - }, - csv: { - scroll: { size: 500, duration: '30s' }, - ...overrides.csv, - }, - roles: { - enabled: false, - ...overrides.roles, - }, - capture: { maxAttempts: 1 }, - export_types: { - pdf: { enabled: true }, - png: { enabled: true }, - csv: { enabled: true }, - ...overrides.export_types, - }, - statefulSettings: { enabled: true }, - } as ReportingConfigType; -}; - export const createMockReportingCore = async ( config: ReportingConfigType, setupDepsMock: ReportingInternalSetup | undefined = undefined, diff --git a/x-pack/plugins/reporting/server/test_helpers/index.ts b/x-pack/plugins/reporting/server/test_helpers/index.ts index 2ad4f4b027af2..781a074a5563e 100644 --- a/x-pack/plugins/reporting/server/test_helpers/index.ts +++ b/x-pack/plugins/reporting/server/test_helpers/index.ts @@ -6,7 +6,6 @@ */ export { - createMockConfigSchema, createMockPluginSetup, createMockPluginStart, createMockReportingCore, diff --git a/x-pack/plugins/reporting/server/types.ts b/x-pack/plugins/reporting/server/types.ts index d2ece5f1e2fab..8f85a75649f3f 100644 --- a/x-pack/plugins/reporting/server/types.ts +++ b/x-pack/plugins/reporting/server/types.ts @@ -5,13 +5,16 @@ * 2.0. */ -import type { CustomRequestHandlerContext, IRouter, KibanaRequest } from '@kbn/core/server'; +import { CustomRequestHandlerContext } from '@kbn/core-http-request-handler-context-server'; +import { IRouter } from '@kbn/core-http-server'; import type { DataPluginStart } from '@kbn/data-plugin/server/plugin'; -import { DiscoverServerPluginStart } from '@kbn/discover-plugin/server'; +import type { DiscoverServerPluginStart } from '@kbn/discover-plugin/server'; import type { PluginSetupContract as FeaturesPluginSetup } from '@kbn/features-plugin/server'; -import { FieldFormatsStart } from '@kbn/field-formats-plugin/server'; +import type { FieldFormatsStart } from '@kbn/field-formats-plugin/server'; import type { LicensingPluginStart } from '@kbn/licensing-plugin/server'; -import type { CancellationToken, TaskRunResult } from '@kbn/reporting-common'; +import type { UrlOrUrlLocatorTuple } from '@kbn/reporting-common/types'; +import type { ReportApiJSON } from '@kbn/reporting-common/types'; +import type { ReportingConfigType } from '@kbn/reporting-server'; import type { ScreenshotModePluginSetup } from '@kbn/screenshot-mode-plugin/server'; import type { PdfScreenshotOptions as BasePdfScreenshotOptions, @@ -29,10 +32,7 @@ import type { TaskManagerStartContract, } from '@kbn/task-manager-plugin/server'; import type { UsageCollectionSetup } from '@kbn/usage-collection-plugin/server'; -import type { Writable } from 'stream'; -import type { BaseParams, BasePayload, ReportApiJSON, UrlOrUrlLocatorTuple } from '../common/types'; -import type { ReportingConfigType } from './config'; -import { ReportingCore } from './core'; + import { ExportTypesRegistry } from './lib'; /** @@ -40,8 +40,6 @@ import { ExportTypesRegistry } from './lib'; */ export interface ReportingSetup { registerExportTypes: ExportTypesRegistry['register']; - getSpaceId: ReportingCore['getSpaceId']; - getScreenshots?: ReportingCore['getScreenshots']; /** * Used to inform plugins if Reporting config is compatible with UI Capabilities / Application Sub-Feature Controls */ @@ -56,47 +54,12 @@ export type ReportingUser = { username: AuthenticatedUser['username'] } | false; export type ScrollConfig = ReportingConfigType['csv']['scroll']; -/** - * Interface of a response to an HTTP request for our plugin to generate a report. - * @public - */ -export interface ReportingJobResponse { - /** - * Contractual field with Watcher: used to automate download of the report once it is finished - * @public - */ - path: string; - /** - * Details of a new report job that was requested - * @public - */ - job: ReportApiJSON; -} - -/** - * Internal Types - */ -// standard type for create job function of any ExportType implementation -export type CreateJobFn = ( - jobParams: JobParamsType, - context: ReportingRequestHandlerContext, - req: KibanaRequest -) => Promise>; - -// standard type for run task function of any ExportType implementation -export type RunTaskFn = ( - jobId: string, - payload: TaskPayloadType, - cancellationToken: CancellationToken, - stream: Writable -) => Promise; - export interface ReportingSetupDeps { features: FeaturesPluginSetup; - screenshotMode?: ScreenshotModePluginSetup; + screenshotMode: ScreenshotModePluginSetup; + taskManager: TaskManagerSetupContract; security?: SecurityPluginSetup; spaces?: SpacesPluginSetup; - taskManager: TaskManagerSetupContract; usageCollection?: UsageCollectionSetup; } @@ -105,9 +68,9 @@ export interface ReportingStartDeps { discover: DiscoverServerPluginStart; fieldFormats: FieldFormatsStart; licensing: LicensingPluginStart; + taskManager: TaskManagerStartContract; screenshotting?: ScreenshottingStart; security?: SecurityPluginStart; - taskManager: TaskManagerStartContract; } export type ReportingRequestHandlerContext = CustomRequestHandlerContext<{ @@ -116,6 +79,23 @@ export type ReportingRequestHandlerContext = CustomRequestHandlerContext<{ export type ReportingPluginRouter = IRouter; +/** + * Interface of a response to an HTTP request for our plugin to generate a report. + * @public + */ +export interface ReportingJobResponse { + /** + * Contractual field with Watcher: used to automate download of the report once it is finished + * @public + */ + path: string; + /** + * Details of a new report job that was requested + * @public + */ + job: ReportApiJSON; +} + export interface PdfScreenshotOptions extends Omit { urls: UrlOrUrlLocatorTuple[]; } @@ -123,5 +103,3 @@ export interface PdfScreenshotOptions extends Omit { urls: UrlOrUrlLocatorTuple[]; } - -export type { BaseParams, BasePayload }; diff --git a/x-pack/plugins/reporting/server/usage/get_export_stats.test.ts b/x-pack/plugins/reporting/server/usage/get_export_stats.test.ts index 3db82290c4671..b901b13a98f8b 100644 --- a/x-pack/plugins/reporting/server/usage/get_export_stats.test.ts +++ b/x-pack/plugins/reporting/server/usage/get_export_stats.test.ts @@ -5,8 +5,9 @@ * 2.0. */ +import { createMockConfigSchema } from '@kbn/reporting-mocks-server'; import { ExportTypesRegistry } from '../lib'; -import { createMockReportingCore, createMockConfigSchema } from '../test_helpers'; +import { createMockReportingCore } from '../test_helpers'; import { getExportStats } from './get_export_stats'; import { getExportTypesHandler } from './get_export_type_handler'; import { ErrorCodeStats, FeatureAvailabilityMap, MetricsStats } from './types'; diff --git a/x-pack/plugins/reporting/server/usage/get_reporting_usage.ts b/x-pack/plugins/reporting/server/usage/get_reporting_usage.ts index c8ef2790932f6..5946e15b2dda3 100644 --- a/x-pack/plugins/reporting/server/usage/get_reporting_usage.ts +++ b/x-pack/plugins/reporting/server/usage/get_reporting_usage.ts @@ -6,9 +6,9 @@ */ import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import type { ElasticsearchClient } from '@kbn/core/server'; +import { REPORTING_SYSTEM_INDEX } from '@kbn/reporting-common'; import { get, pick } from 'lodash'; import type { GetLicense } from '.'; -import { REPORTING_SYSTEM_INDEX } from '../../common/constants'; import type { ExportTypesRegistry } from '../lib/export_types_registry'; import { FIELD_EXECUTION_TIME_MS, diff --git a/x-pack/plugins/reporting/server/usage/reporting_usage_collector.test.ts b/x-pack/plugins/reporting/server/usage/reporting_usage_collector.test.ts index 55111f2338877..d7a0492005868 100644 --- a/x-pack/plugins/reporting/server/usage/reporting_usage_collector.test.ts +++ b/x-pack/plugins/reporting/server/usage/reporting_usage_collector.test.ts @@ -5,20 +5,21 @@ * 2.0. */ -import { loggerMock } from '@kbn/logging-mocks'; import type { ElasticsearchClientMock } from '@kbn/core/server/mocks'; +import { loggerMock } from '@kbn/logging-mocks'; +import { createMockConfigSchema } from '@kbn/reporting-mocks-server'; import { Collector, createCollectorFetchContextMock, usageCollectionPluginMock, } from '@kbn/usage-collection-plugin/server/mocks'; -import { createMockConfigSchema, createMockReportingCore } from '../test_helpers'; import { FeaturesAvailability } from '.'; +import { ExportTypesRegistry } from '../lib'; +import { createMockReportingCore } from '../test_helpers'; import { getReportingUsageCollector, registerReportingUsageCollector, } from './reporting_usage_collector'; -import { ExportTypesRegistry } from '../lib'; const getLicenseMock = (licenseType = 'gold') => diff --git a/x-pack/plugins/reporting/tsconfig.json b/x-pack/plugins/reporting/tsconfig.json index be183ef08a366..53a4ab34eb197 100644 --- a/x-pack/plugins/reporting/tsconfig.json +++ b/x-pack/plugins/reporting/tsconfig.json @@ -10,7 +10,6 @@ "@kbn/discover-plugin", "@kbn/embeddable-plugin", "@kbn/kibana-react-plugin", - "@kbn/kibana-utils-plugin", "@kbn/management-plugin", "@kbn/screenshot-mode-plugin", "@kbn/share-plugin", @@ -36,12 +35,21 @@ "@kbn/core-http-server", "@kbn/core-test-helpers-test-utils", "@kbn/safer-lodash-set", - "@kbn/generate-csv", "@kbn/reporting-common", "@kbn/saved-search-plugin", "@kbn/core-http-router-server-internal", + "@kbn/reporting-server", + "@kbn/reporting-export-types-csv", + "@kbn/reporting-export-types-pdf", + "@kbn/reporting-export-types-png", + "@kbn/reporting-export-types-pdf-common", + "@kbn/reporting-export-types-csv-common", "@kbn/core-http-common", "@kbn/react-kibana-context-theme", + "@kbn/reporting-export-types-png-common", + "@kbn/reporting-mocks-server", + "@kbn/core-http-request-handler-context-server", + "@kbn/reporting-public", ], "exclude": [ "target/**/*", diff --git a/x-pack/plugins/rollup/server/index.ts b/x-pack/plugins/rollup/server/index.ts index 8f41f7f9cf6fe..fd3f92e126840 100644 --- a/x-pack/plugins/rollup/server/index.ts +++ b/x-pack/plugins/rollup/server/index.ts @@ -6,9 +6,10 @@ */ import { PluginInitializerContext } from '@kbn/core/server'; -import { RollupPlugin } from './plugin'; export { config } from './config'; -export const plugin = (pluginInitializerContext: PluginInitializerContext) => - new RollupPlugin(pluginInitializerContext); +export const plugin = async (pluginInitializerContext: PluginInitializerContext) => { + const { RollupPlugin } = await import('./plugin'); + return new RollupPlugin(pluginInitializerContext); +}; diff --git a/x-pack/plugins/rule_registry/server/index.ts b/x-pack/plugins/rule_registry/server/index.ts index c39aeb158be74..826d0d6f23bab 100644 --- a/x-pack/plugins/rule_registry/server/index.ts +++ b/x-pack/plugins/rule_registry/server/index.ts @@ -9,7 +9,6 @@ /* eslint-disable @kbn/eslint/no_export_all */ import { PluginInitializerContext } from '@kbn/core/server'; -import { RuleRegistryPlugin } from './plugin'; export type { RuleRegistryPluginSetupContract, RuleRegistryPluginStartContract } from './plugin'; export type { IRuleDataService, RuleDataPluginService } from './rule_data_plugin_service'; @@ -37,5 +36,7 @@ export { createPersistenceRuleTypeWrapper } from './utils/create_persistence_rul export * from './utils/persistence_types'; export type { AlertsClient } from './alert_data_client/alerts_client'; -export const plugin = (initContext: PluginInitializerContext) => - new RuleRegistryPlugin(initContext); +export const plugin = async (initContext: PluginInitializerContext) => { + const { RuleRegistryPlugin } = await import('./plugin'); + return new RuleRegistryPlugin(initContext); +}; diff --git a/x-pack/plugins/saved_objects_tagging/server/index.ts b/x-pack/plugins/saved_objects_tagging/server/index.ts index b9fcdcdbb7b4e..8c0d4f98b6994 100644 --- a/x-pack/plugins/saved_objects_tagging/server/index.ts +++ b/x-pack/plugins/saved_objects_tagging/server/index.ts @@ -6,7 +6,6 @@ */ import { PluginInitializerContext } from '@kbn/core/server'; -import { SavedObjectTaggingPlugin } from './plugin'; export { config } from './config'; export type { @@ -17,5 +16,7 @@ export type { export type { IAssignmentService } from './services'; export type { ITagsClient } from '../common'; -export const plugin = (initializerContext: PluginInitializerContext) => - new SavedObjectTaggingPlugin(); +export const plugin = async (initializerContext: PluginInitializerContext) => { + const { SavedObjectTaggingPlugin } = await import('./plugin'); + return new SavedObjectTaggingPlugin(); +}; diff --git a/x-pack/plugins/screenshotting/common/index.ts b/x-pack/plugins/screenshotting/common/index.ts index 3e36d061cba49..cb89ef794eb91 100644 --- a/x-pack/plugins/screenshotting/common/index.ts +++ b/x-pack/plugins/screenshotting/common/index.ts @@ -5,13 +5,16 @@ * 2.0. */ +import * as errors from './errors'; +export { errors }; + export { SCREENSHOTTING_APP_ID, SCREENSHOTTING_EXPRESSION, SCREENSHOTTING_EXPRESSION_INPUT, } from './expression'; + export type { LayoutParams, LayoutType } from './layout'; -export { errors }; -import * as errors from './errors'; +export type { PerformanceMetrics } from './types'; export const PLUGIN_ID = 'screenshotting'; diff --git a/x-pack/plugins/screenshotting/common/types.ts b/x-pack/plugins/screenshotting/common/types.ts new file mode 100644 index 0000000000000..3e6ad952baf55 --- /dev/null +++ b/x-pack/plugins/screenshotting/common/types.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. + */ + +/** + * Collected performance metrics during a screenshotting session. + */ +export interface PerformanceMetrics { + /** + * The percentage of CPU time spent by the browser divided by number or cores. + */ + cpu?: number; + + /** + * The percentage of CPU in percent untis. + */ + cpuInPercentage?: number; + + /** + * The total amount of memory used by the browser. + */ + memory?: number; + + /** + * The total amount of memory used by the browser in megabytes. + */ + memoryInMegabytes?: number; +} diff --git a/x-pack/plugins/screenshotting/server/browsers/chromium/driver_factory/index.ts b/x-pack/plugins/screenshotting/server/browsers/chromium/driver_factory/index.ts index ce8b8a3a209d9..9558b1f6a875f 100644 --- a/x-pack/plugins/screenshotting/server/browsers/chromium/driver_factory/index.ts +++ b/x-pack/plugins/screenshotting/server/browsers/chromium/driver_factory/index.ts @@ -26,13 +26,14 @@ import { takeUntil, tap, } from 'rxjs/operators'; +import { PerformanceMetrics } from '../../../../common/types'; import { getChromiumDisconnectedError } from '..'; import { errors } from '../../../../common'; import { ConfigType } from '../../../config'; import { safeChildProcess } from '../../safe_child_process'; import { HeadlessChromiumDriver } from '../driver'; import { args } from './args'; -import { getMetrics, PerformanceMetrics } from './metrics'; +import { getMetrics } from './metrics'; interface CreatePageOptions { browserTimezone?: string; @@ -455,5 +456,3 @@ export class HeadlessChromiumDriverFactory { ); } } - -export type { PerformanceMetrics }; diff --git a/x-pack/plugins/screenshotting/server/browsers/chromium/driver_factory/metrics.ts b/x-pack/plugins/screenshotting/server/browsers/chromium/driver_factory/metrics.ts index 6e9971324ae4b..9c48a1e1fde2a 100644 --- a/x-pack/plugins/screenshotting/server/browsers/chromium/driver_factory/metrics.ts +++ b/x-pack/plugins/screenshotting/server/browsers/chromium/driver_factory/metrics.ts @@ -7,6 +7,7 @@ import type { Metrics as PuppeteerMetrics } from 'puppeteer'; import { cpus } from 'os'; +import { PerformanceMetrics } from '../../../../common/types'; declare module 'puppeteer' { interface CDPSession { @@ -29,31 +30,6 @@ interface NormalizedMetrics extends Required { ProcessTime: number; } -/** - * Collected performance metrics during a screenshotting session. - */ -export interface PerformanceMetrics { - /** - * The percentage of CPU time spent by the browser divided by number or cores. - */ - cpu: number; - - /** - * The percentage of CPU in percent untis. - */ - cpuInPercentage: number; - - /** - * The total amount of memory used by the browser. - */ - memory: number; - - /** - * The total amount of memory used by the browser in megabytes. - */ - memoryInMegabytes: number; -} - function normalizeMetrics({ metrics }: Metrics) { return Object.fromEntries( metrics.map(({ name, value }) => [name, value]) diff --git a/x-pack/plugins/screenshotting/server/browsers/chromium/index.ts b/x-pack/plugins/screenshotting/server/browsers/chromium/index.ts index 672ea2ec5f020..e3f96f3a7445b 100644 --- a/x-pack/plugins/screenshotting/server/browsers/chromium/index.ts +++ b/x-pack/plugins/screenshotting/server/browsers/chromium/index.ts @@ -20,6 +20,5 @@ export const getDisallowedOutgoingUrlError = (interceptedUrl: string) => export { HeadlessChromiumDriver } from './driver'; export type { Context } from './driver'; export { DEFAULT_VIEWPORT, HeadlessChromiumDriverFactory } from './driver_factory'; -export type { PerformanceMetrics } from './driver_factory'; export { ChromiumArchivePaths } from './paths'; export type { PackageInfo } from './paths'; diff --git a/x-pack/plugins/screenshotting/server/browsers/index.ts b/x-pack/plugins/screenshotting/server/browsers/index.ts index 15c8b2b2db06b..0b6402a0bd6fb 100644 --- a/x-pack/plugins/screenshotting/server/browsers/index.ts +++ b/x-pack/plugins/screenshotting/server/browsers/index.ts @@ -7,7 +7,7 @@ export { download } from './download'; export { install } from './install'; -export type { Context, PerformanceMetrics } from './chromium'; +export type { Context } from './chromium'; export { getChromiumDisconnectedError, ChromiumArchivePaths, diff --git a/x-pack/plugins/screenshotting/server/index.ts b/x-pack/plugins/screenshotting/server/index.ts index 10d445b5e0eb1..414fde21c85a9 100755 --- a/x-pack/plugins/screenshotting/server/index.ts +++ b/x-pack/plugins/screenshotting/server/index.ts @@ -5,13 +5,14 @@ * 2.0. */ -import { ScreenshottingPlugin } from './plugin'; +import { PluginInitializerContext } from '@kbn/core-plugins-server'; /** * Screenshotting plugin entry point. */ -export function plugin(...args: ConstructorParameters) { - return new ScreenshottingPlugin(...args); +export async function plugin(pluginInitializerContext: PluginInitializerContext) { + const { ScreenshottingPlugin } = await import('./plugin'); + return new ScreenshottingPlugin(pluginInitializerContext); } export { config } from './config'; diff --git a/x-pack/plugins/screenshotting/server/screenshots/index.ts b/x-pack/plugins/screenshotting/server/screenshots/index.ts index b1a0d98fe8a27..7f7882cb26b2e 100644 --- a/x-pack/plugins/screenshotting/server/screenshots/index.ts +++ b/x-pack/plugins/screenshotting/server/screenshots/index.ts @@ -9,7 +9,7 @@ import type { KibanaRequest } from '@kbn/core/server'; import type { ExpressionAstExpression } from '@kbn/expressions-plugin/common'; import type { Optional } from '@kbn/utility-types'; import { LayoutParams } from '../../common'; -import { PerformanceMetrics } from '../browsers'; +import { PerformanceMetrics } from '../../common/types'; import { PdfScreenshotOptions, PdfScreenshotResult, diff --git a/x-pack/plugins/screenshotting/tsconfig.json b/x-pack/plugins/screenshotting/tsconfig.json index 3749a60fc4fe4..f23b380911f0f 100644 --- a/x-pack/plugins/screenshotting/tsconfig.json +++ b/x-pack/plugins/screenshotting/tsconfig.json @@ -25,6 +25,7 @@ "@kbn/core-logging-server-mocks", "@kbn/logging-mocks", "@kbn/core-http-server", + "@kbn/core-plugins-server", ], "exclude": [ "target/**/*", diff --git a/x-pack/plugins/searchprofiler/server/index.ts b/x-pack/plugins/searchprofiler/server/index.ts index 95f5b28435738..53ef83285622e 100644 --- a/x-pack/plugins/searchprofiler/server/index.ts +++ b/x-pack/plugins/searchprofiler/server/index.ts @@ -6,8 +6,8 @@ */ import { PluginInitializerContext } from '@kbn/core/server'; -import { SearchProfilerServerPlugin } from './plugin'; -export const plugin = (ctx: PluginInitializerContext) => { +export const plugin = async (ctx: PluginInitializerContext) => { + const { SearchProfilerServerPlugin } = await import('./plugin'); return new SearchProfilerServerPlugin(ctx); }; diff --git a/x-pack/plugins/security/public/management/role_mappings/role_mappings_management_app.test.tsx b/x-pack/plugins/security/public/management/role_mappings/role_mappings_management_app.test.tsx index 2f0910627be9b..8e11a1929ca16 100644 --- a/x-pack/plugins/security/public/management/role_mappings/role_mappings_management_app.test.tsx +++ b/x-pack/plugins/security/public/management/role_mappings/role_mappings_management_app.test.tsx @@ -89,7 +89,7 @@ describe('roleMappingsManagementApp', () => { expect(docTitle.reset).not.toHaveBeenCalled(); expect(container).toMatchInlineSnapshot(`
    - Role Mappings Page: {"notifications":{"toasts":{}},"rolesAPIClient":{"http":{"basePath":{"basePath":"","serverBasePath":""},"anonymousPaths":{},"externalUrl":{}}},"roleMappingsAPI":{"http":{"basePath":{"basePath":"","serverBasePath":""},"anonymousPaths":{},"externalUrl":{}}},"docLinks":{},"history":{"action":"PUSH","length":1,"location":{"pathname":"/","search":"","hash":""}},"readOnly":false} + Role Mappings Page: {"notifications":{"toasts":{}},"rolesAPIClient":{"http":{"basePath":{"basePath":"","serverBasePath":"","assetsHrefBase":""},"anonymousPaths":{},"externalUrl":{},"staticAssets":{}}},"roleMappingsAPI":{"http":{"basePath":{"basePath":"","serverBasePath":"","assetsHrefBase":""},"anonymousPaths":{},"externalUrl":{},"staticAssets":{}}},"docLinks":{},"history":{"action":"PUSH","length":1,"location":{"pathname":"/","search":"","hash":""}},"readOnly":false}
    `); @@ -111,7 +111,7 @@ describe('roleMappingsManagementApp', () => { expect(docTitle.reset).not.toHaveBeenCalled(); expect(container).toMatchInlineSnapshot(`
    - Role Mappings Page: {"notifications":{"toasts":{}},"rolesAPIClient":{"http":{"basePath":{"basePath":"","serverBasePath":""},"anonymousPaths":{},"externalUrl":{}}},"roleMappingsAPI":{"http":{"basePath":{"basePath":"","serverBasePath":""},"anonymousPaths":{},"externalUrl":{}}},"docLinks":{},"history":{"action":"PUSH","length":1,"location":{"pathname":"/","search":"","hash":""}},"readOnly":true} + Role Mappings Page: {"notifications":{"toasts":{}},"rolesAPIClient":{"http":{"basePath":{"basePath":"","serverBasePath":"","assetsHrefBase":""},"anonymousPaths":{},"externalUrl":{},"staticAssets":{}}},"roleMappingsAPI":{"http":{"basePath":{"basePath":"","serverBasePath":"","assetsHrefBase":""},"anonymousPaths":{},"externalUrl":{},"staticAssets":{}}},"docLinks":{},"history":{"action":"PUSH","length":1,"location":{"pathname":"/","search":"","hash":""}},"readOnly":true}
    `); @@ -136,7 +136,7 @@ describe('roleMappingsManagementApp', () => { expect(docTitle.reset).not.toHaveBeenCalled(); expect(container).toMatchInlineSnapshot(`
    - Role Mapping Edit Page: {"action":"edit","roleMappingsAPI":{"http":{"basePath":{"basePath":"","serverBasePath":""},"anonymousPaths":{},"externalUrl":{}}},"rolesAPIClient":{"http":{"basePath":{"basePath":"","serverBasePath":""},"anonymousPaths":{},"externalUrl":{}}},"notifications":{"toasts":{}},"docLinks":{},"history":{"action":"PUSH","length":1,"location":{"pathname":"/edit","search":"","hash":""}},"readOnly":false} + Role Mapping Edit Page: {"action":"edit","roleMappingsAPI":{"http":{"basePath":{"basePath":"","serverBasePath":"","assetsHrefBase":""},"anonymousPaths":{},"externalUrl":{},"staticAssets":{}}},"rolesAPIClient":{"http":{"basePath":{"basePath":"","serverBasePath":"","assetsHrefBase":""},"anonymousPaths":{},"externalUrl":{},"staticAssets":{}}},"notifications":{"toasts":{}},"docLinks":{},"history":{"action":"PUSH","length":1,"location":{"pathname":"/edit","search":"","hash":""}},"readOnly":false}
    `); @@ -166,7 +166,7 @@ describe('roleMappingsManagementApp', () => { expect(docTitle.reset).not.toHaveBeenCalled(); expect(container).toMatchInlineSnapshot(`
    - Role Mapping Edit Page: {"action":"edit","name":"role@mapping","roleMappingsAPI":{"http":{"basePath":{"basePath":"","serverBasePath":""},"anonymousPaths":{},"externalUrl":{}}},"rolesAPIClient":{"http":{"basePath":{"basePath":"","serverBasePath":""},"anonymousPaths":{},"externalUrl":{}}},"notifications":{"toasts":{}},"docLinks":{},"history":{"action":"PUSH","length":1,"location":{"pathname":"/edit/role@mapping","search":"","hash":""}},"readOnly":false} + Role Mapping Edit Page: {"action":"edit","name":"role@mapping","roleMappingsAPI":{"http":{"basePath":{"basePath":"","serverBasePath":"","assetsHrefBase":""},"anonymousPaths":{},"externalUrl":{},"staticAssets":{}}},"rolesAPIClient":{"http":{"basePath":{"basePath":"","serverBasePath":"","assetsHrefBase":""},"anonymousPaths":{},"externalUrl":{},"staticAssets":{}}},"notifications":{"toasts":{}},"docLinks":{},"history":{"action":"PUSH","length":1,"location":{"pathname":"/edit/role@mapping","search":"","hash":""}},"readOnly":false}
    `); @@ -197,7 +197,7 @@ describe('roleMappingsManagementApp', () => { expect(docTitle.reset).not.toHaveBeenCalled(); expect(container).toMatchInlineSnapshot(`
    - Role Mapping Edit Page: {"action":"edit","name":"role@mapping","roleMappingsAPI":{"http":{"basePath":{"basePath":"","serverBasePath":""},"anonymousPaths":{},"externalUrl":{}}},"rolesAPIClient":{"http":{"basePath":{"basePath":"","serverBasePath":""},"anonymousPaths":{},"externalUrl":{}}},"notifications":{"toasts":{}},"docLinks":{},"history":{"action":"PUSH","length":1,"location":{"pathname":"/edit/role@mapping","search":"","hash":""}},"readOnly":true} + Role Mapping Edit Page: {"action":"edit","name":"role@mapping","roleMappingsAPI":{"http":{"basePath":{"basePath":"","serverBasePath":"","assetsHrefBase":""},"anonymousPaths":{},"externalUrl":{},"staticAssets":{}}},"rolesAPIClient":{"http":{"basePath":{"basePath":"","serverBasePath":"","assetsHrefBase":""},"anonymousPaths":{},"externalUrl":{},"staticAssets":{}}},"notifications":{"toasts":{}},"docLinks":{},"history":{"action":"PUSH","length":1,"location":{"pathname":"/edit/role@mapping","search":"","hash":""}},"readOnly":true}
    `); diff --git a/x-pack/plugins/security/public/management/roles/roles_management_app.test.tsx b/x-pack/plugins/security/public/management/roles/roles_management_app.test.tsx index 5e9d5fcc56350..300f5e195b510 100644 --- a/x-pack/plugins/security/public/management/roles/roles_management_app.test.tsx +++ b/x-pack/plugins/security/public/management/roles/roles_management_app.test.tsx @@ -90,7 +90,7 @@ describe('rolesManagementApp', () => { expect(docTitle.reset).not.toHaveBeenCalled(); expect(container).toMatchInlineSnapshot(`
    - Roles Page: {"notifications":{"toasts":{}},"rolesAPIClient":{"http":{"basePath":{"basePath":"","serverBasePath":""},"anonymousPaths":{},"externalUrl":{}}},"history":{"action":"PUSH","length":1,"location":{"pathname":"/","search":"","hash":""}},"readOnly":false} + Roles Page: {"notifications":{"toasts":{}},"rolesAPIClient":{"http":{"basePath":{"basePath":"","serverBasePath":"","assetsHrefBase":""},"anonymousPaths":{},"externalUrl":{},"staticAssets":{}}},"history":{"action":"PUSH","length":1,"location":{"pathname":"/","search":"","hash":""}},"readOnly":false}
    `); @@ -112,7 +112,7 @@ describe('rolesManagementApp', () => { expect(docTitle.reset).not.toHaveBeenCalled(); expect(container).toMatchInlineSnapshot(`
    - Role Edit Page: {"action":"edit","rolesAPIClient":{"http":{"basePath":{"basePath":"","serverBasePath":""},"anonymousPaths":{},"externalUrl":{}}},"userAPIClient":{"http":{"basePath":{"basePath":"","serverBasePath":""},"anonymousPaths":{},"externalUrl":{}}},"indicesAPIClient":{"fieldCache":{},"http":{"basePath":{"basePath":"","serverBasePath":""},"anonymousPaths":{},"externalUrl":{}}},"privilegesAPIClient":{"http":{"basePath":{"basePath":"","serverBasePath":""},"anonymousPaths":{},"externalUrl":{}}},"http":{"basePath":{"basePath":"","serverBasePath":""},"anonymousPaths":{},"externalUrl":{}},"notifications":{"toasts":{}},"fatalErrors":{},"license":{"features$":{}},"docLinks":{},"uiCapabilities":{"catalogue":{},"management":{},"navLinks":{},"roles":{"save":true}},"history":{"action":"PUSH","length":1,"location":{"pathname":"/edit","search":"","hash":""}}} + Role Edit Page: {"action":"edit","rolesAPIClient":{"http":{"basePath":{"basePath":"","serverBasePath":"","assetsHrefBase":""},"anonymousPaths":{},"externalUrl":{},"staticAssets":{}}},"userAPIClient":{"http":{"basePath":{"basePath":"","serverBasePath":"","assetsHrefBase":""},"anonymousPaths":{},"externalUrl":{},"staticAssets":{}}},"indicesAPIClient":{"fieldCache":{},"http":{"basePath":{"basePath":"","serverBasePath":"","assetsHrefBase":""},"anonymousPaths":{},"externalUrl":{},"staticAssets":{}}},"privilegesAPIClient":{"http":{"basePath":{"basePath":"","serverBasePath":"","assetsHrefBase":""},"anonymousPaths":{},"externalUrl":{},"staticAssets":{}}},"http":{"basePath":{"basePath":"","serverBasePath":"","assetsHrefBase":""},"anonymousPaths":{},"externalUrl":{},"staticAssets":{}},"notifications":{"toasts":{}},"fatalErrors":{},"license":{"features$":{}},"docLinks":{},"uiCapabilities":{"catalogue":{},"management":{},"navLinks":{},"roles":{"save":true}},"history":{"action":"PUSH","length":1,"location":{"pathname":"/edit","search":"","hash":""}}}
    `); @@ -139,7 +139,7 @@ describe('rolesManagementApp', () => { expect(docTitle.reset).not.toHaveBeenCalled(); expect(container).toMatchInlineSnapshot(`
    - Role Edit Page: {"action":"edit","roleName":"role@name","rolesAPIClient":{"http":{"basePath":{"basePath":"","serverBasePath":""},"anonymousPaths":{},"externalUrl":{}}},"userAPIClient":{"http":{"basePath":{"basePath":"","serverBasePath":""},"anonymousPaths":{},"externalUrl":{}}},"indicesAPIClient":{"fieldCache":{},"http":{"basePath":{"basePath":"","serverBasePath":""},"anonymousPaths":{},"externalUrl":{}}},"privilegesAPIClient":{"http":{"basePath":{"basePath":"","serverBasePath":""},"anonymousPaths":{},"externalUrl":{}}},"http":{"basePath":{"basePath":"","serverBasePath":""},"anonymousPaths":{},"externalUrl":{}},"notifications":{"toasts":{}},"fatalErrors":{},"license":{"features$":{}},"docLinks":{},"uiCapabilities":{"catalogue":{},"management":{},"navLinks":{},"roles":{"save":true}},"history":{"action":"PUSH","length":1,"location":{"pathname":"/edit/role@name","search":"","hash":""}}} + Role Edit Page: {"action":"edit","roleName":"role@name","rolesAPIClient":{"http":{"basePath":{"basePath":"","serverBasePath":"","assetsHrefBase":""},"anonymousPaths":{},"externalUrl":{},"staticAssets":{}}},"userAPIClient":{"http":{"basePath":{"basePath":"","serverBasePath":"","assetsHrefBase":""},"anonymousPaths":{},"externalUrl":{},"staticAssets":{}}},"indicesAPIClient":{"fieldCache":{},"http":{"basePath":{"basePath":"","serverBasePath":"","assetsHrefBase":""},"anonymousPaths":{},"externalUrl":{},"staticAssets":{}}},"privilegesAPIClient":{"http":{"basePath":{"basePath":"","serverBasePath":"","assetsHrefBase":""},"anonymousPaths":{},"externalUrl":{},"staticAssets":{}}},"http":{"basePath":{"basePath":"","serverBasePath":"","assetsHrefBase":""},"anonymousPaths":{},"externalUrl":{},"staticAssets":{}},"notifications":{"toasts":{}},"fatalErrors":{},"license":{"features$":{}},"docLinks":{},"uiCapabilities":{"catalogue":{},"management":{},"navLinks":{},"roles":{"save":true}},"history":{"action":"PUSH","length":1,"location":{"pathname":"/edit/role@name","search":"","hash":""}}}
    `); @@ -166,7 +166,7 @@ describe('rolesManagementApp', () => { expect(docTitle.reset).not.toHaveBeenCalled(); expect(container).toMatchInlineSnapshot(`
    - Role Edit Page: {"action":"clone","roleName":"someRoleName","rolesAPIClient":{"http":{"basePath":{"basePath":"","serverBasePath":""},"anonymousPaths":{},"externalUrl":{}}},"userAPIClient":{"http":{"basePath":{"basePath":"","serverBasePath":""},"anonymousPaths":{},"externalUrl":{}}},"indicesAPIClient":{"fieldCache":{},"http":{"basePath":{"basePath":"","serverBasePath":""},"anonymousPaths":{},"externalUrl":{}}},"privilegesAPIClient":{"http":{"basePath":{"basePath":"","serverBasePath":""},"anonymousPaths":{},"externalUrl":{}}},"http":{"basePath":{"basePath":"","serverBasePath":""},"anonymousPaths":{},"externalUrl":{}},"notifications":{"toasts":{}},"fatalErrors":{},"license":{"features$":{}},"docLinks":{},"uiCapabilities":{"catalogue":{},"management":{},"navLinks":{},"roles":{"save":true}},"history":{"action":"PUSH","length":1,"location":{"pathname":"/clone/someRoleName","search":"","hash":""}}} + Role Edit Page: {"action":"clone","roleName":"someRoleName","rolesAPIClient":{"http":{"basePath":{"basePath":"","serverBasePath":"","assetsHrefBase":""},"anonymousPaths":{},"externalUrl":{},"staticAssets":{}}},"userAPIClient":{"http":{"basePath":{"basePath":"","serverBasePath":"","assetsHrefBase":""},"anonymousPaths":{},"externalUrl":{},"staticAssets":{}}},"indicesAPIClient":{"fieldCache":{},"http":{"basePath":{"basePath":"","serverBasePath":"","assetsHrefBase":""},"anonymousPaths":{},"externalUrl":{},"staticAssets":{}}},"privilegesAPIClient":{"http":{"basePath":{"basePath":"","serverBasePath":"","assetsHrefBase":""},"anonymousPaths":{},"externalUrl":{},"staticAssets":{}}},"http":{"basePath":{"basePath":"","serverBasePath":"","assetsHrefBase":""},"anonymousPaths":{},"externalUrl":{},"staticAssets":{}},"notifications":{"toasts":{}},"fatalErrors":{},"license":{"features$":{}},"docLinks":{},"uiCapabilities":{"catalogue":{},"management":{},"navLinks":{},"roles":{"save":true}},"history":{"action":"PUSH","length":1,"location":{"pathname":"/clone/someRoleName","search":"","hash":""}}}
    `); diff --git a/x-pack/plugins/security/public/session/unauthorized_response_http_interceptor.test.ts b/x-pack/plugins/security/public/session/unauthorized_response_http_interceptor.test.ts index 7f3f0d57d449c..202d1b2d578c6 100644 --- a/x-pack/plugins/security/public/session/unauthorized_response_http_interceptor.test.ts +++ b/x-pack/plugins/security/public/session/unauthorized_response_http_interceptor.test.ts @@ -8,6 +8,7 @@ // @ts-ignore import fetchMock from 'fetch-mock/es5/client'; +import type { HttpSetup } from '@kbn/core/public'; import { applicationServiceMock } from '@kbn/core/public/mocks'; import { setup } from '@kbn/core-test-helpers-http-setup-browser'; @@ -30,7 +31,7 @@ const setupHttp = (basePath: string) => { const { http } = setup((injectedMetadata) => { injectedMetadata.getBasePath.mockReturnValue(basePath); }); - return http; + return http as HttpSetup; }; const tenant = ''; const application = applicationServiceMock.createStartContract(); diff --git a/x-pack/plugins/security/server/index.ts b/x-pack/plugins/security/server/index.ts index 4cf199ef6d686..3d5cd022b4c96 100644 --- a/x-pack/plugins/security/server/index.ts +++ b/x-pack/plugins/security/server/index.ts @@ -16,7 +16,6 @@ import type { RecursiveReadonly } from '@kbn/utility-types'; import { ConfigSchema } from './config'; import { securityConfigDeprecationProvider } from './config_deprecations'; import type { PluginSetupDependencies, SecurityPluginSetup, SecurityPluginStart } from './plugin'; -import { SecurityPlugin } from './plugin'; // These exports are part of public Security plugin contract, any change in signature of exported // functions or removal of exports should be considered as a breaking change. @@ -63,4 +62,7 @@ export const plugin: PluginInitializer< RecursiveReadonly, RecursiveReadonly, PluginSetupDependencies -> = (initializerContext: PluginInitializerContext) => new SecurityPlugin(initializerContext); +> = async (initializerContext: PluginInitializerContext) => { + const { SecurityPlugin } = await import('./plugin'); + return new SecurityPlugin(initializerContext); +}; diff --git a/x-pack/plugins/security_solution/public/common/components/visualization_actions/actions.tsx b/x-pack/plugins/security_solution/public/common/components/visualization_actions/actions.tsx index 0825aacfee410..5527e0eca44d6 100644 --- a/x-pack/plugins/security_solution/public/common/components/visualization_actions/actions.tsx +++ b/x-pack/plugins/security_solution/public/common/components/visualization_actions/actions.tsx @@ -10,6 +10,7 @@ import type { Action, ActionExecutionContext } from '@kbn/ui-actions-plugin/publ import React, { useCallback, useMemo, useState } from 'react'; import styled from 'styled-components'; +import type { LensEmbeddableInput } from '@kbn/lens-plugin/public'; import { InputsModelId } from '../../store/inputs/constants'; import { useKibana } from '../../lib/kibana/kibana_react'; import { ModalInspectQuery } from '../inspect/modal'; @@ -18,6 +19,7 @@ import { useInspect } from '../inspect/use_inspect'; import { useLensAttributes } from './use_lens_attributes'; import { useAddToExistingCase } from './use_add_to_existing_case'; import { useAddToNewCase } from './use_add_to_new_case'; +import { useSaveToLibrary } from './use_save_to_library'; import type { VisualizationActionsProps } from './types'; import { ADD_TO_EXISTING_CASE, @@ -25,9 +27,11 @@ import { INSPECT, MORE_ACTIONS, OPEN_IN_LENS, + ADDED_TO_LIBRARY, } from './translations'; import { VISUALIZATION_ACTIONS_BUTTON_CLASS } from './utils'; import { SourcererScopeName } from '../../store/sourcerer/model'; +import { useAppToasts } from '../../hooks/use_app_toasts'; const Wrapper = styled.div` &.viz-actions { @@ -62,9 +66,19 @@ const VisualizationActionsComponent: React.FC = ({ }) => { const { lens } = useKibana().services; - const { canUseEditor, navigateToPrefilledEditor } = lens; + const { canUseEditor, navigateToPrefilledEditor, SaveModalComponent } = lens; const [isPopoverOpen, setPopover] = useState(false); const [isInspectModalOpen, setIsInspectModalOpen] = useState(false); + const [isSaveModalVisible, setIsSaveModalVisible] = useState(false); + const { addSuccess } = useAppToasts(); + const onSave = useCallback(() => { + setIsSaveModalVisible(false); + addSuccess(ADDED_TO_LIBRARY); + }, [addSuccess]); + const onClose = useCallback(() => { + setIsSaveModalVisible(false); + }, []); + const hasPermission = canUseEditor(); const onButtonClick = useCallback(() => { setPopover(!isPopoverOpen); @@ -116,6 +130,10 @@ const VisualizationActionsComponent: React.FC = ({ ); }, [attributes, navigateToPrefilledEditor, timerange]); + const { openSaveVisualizationFlyout, disableVisualizations } = useSaveToLibrary({ + attributes, + }); + const onOpenInspectModal = useCallback(() => { closePopover(); setIsInspectModalOpen(true); @@ -146,11 +164,6 @@ const VisualizationActionsComponent: React.FC = ({ queryId, }); - const disabledOpenInLens = useMemo( - () => !canUseEditor() || attributes == null, - [attributes, canUseEditor] - ); - const items = useMemo(() => { const context = {} as ActionExecutionContext; const extraActionsItems = @@ -197,11 +210,24 @@ const VisualizationActionsComponent: React.FC = ({ > {ADD_TO_EXISTING_CASE} , + ...(hasPermission + ? [ + + {ADDED_TO_LIBRARY} + , + ] + : []), {OPEN_IN_LENS} @@ -210,8 +236,9 @@ const VisualizationActionsComponent: React.FC = ({ : []), ]; }, [ + hasPermission, disableInspectButton, - disabledOpenInLens, + disableVisualizations, extraActions, handleInspectButtonClick, isAddToExistingCaseDisabled, @@ -219,6 +246,7 @@ const VisualizationActionsComponent: React.FC = ({ onAddToExistingCaseClicked, onAddToNewCaseClicked, onOpenInLens, + openSaveVisualizationFlyout, withDefaultActions, ]); @@ -261,6 +289,13 @@ const VisualizationActionsComponent: React.FC = ({ title={inspectTitle} /> )} + {isSaveModalVisible && hasPermission && ( + + )} ); }; diff --git a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/common/authentication.ts b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/common/authentication.ts index a444d479d2ba0..013a05c840fbf 100644 --- a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/common/authentication.ts +++ b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/common/authentication.ts @@ -6,8 +6,8 @@ */ import { - AUTHENCICATION_FAILURE_CHART_LABEL, - AUTHENCICATION_SUCCESS_CHART_LABEL, + AUTHENTICATION_FAILURE_CHART_LABEL, + AUTHENTICATION_SUCCESS_CHART_LABEL, } from '../../translations'; import type { LensAttributes } from '../../types'; @@ -115,7 +115,7 @@ export const authenticationLensAttributes: LensAttributes = { }, }, '5417777d-d9d9-4268-9cdc-eb29b873bd65': { - label: AUTHENCICATION_SUCCESS_CHART_LABEL, + label: AUTHENTICATION_SUCCESS_CHART_LABEL, dataType: 'number', operationType: 'count', isBucketed: false, @@ -148,7 +148,7 @@ export const authenticationLensAttributes: LensAttributes = { }, }, 'a3bf9dc1-c8d2-42d6-9e60-31892a4c509e': { - label: AUTHENCICATION_FAILURE_CHART_LABEL, + label: AUTHENTICATION_FAILURE_CHART_LABEL, dataType: 'number', operationType: 'count', isBucketed: false, diff --git a/x-pack/plugins/security_solution/public/common/components/visualization_actions/translations.ts b/x-pack/plugins/security_solution/public/common/components/visualization_actions/translations.ts index 8f21d61bc869b..2e6e6d2b8f3ef 100644 --- a/x-pack/plugins/security_solution/public/common/components/visualization_actions/translations.ts +++ b/x-pack/plugins/security_solution/public/common/components/visualization_actions/translations.ts @@ -67,7 +67,7 @@ export const SUCCESS_CHART_LABEL = i18n.translate( } ); -export const AUTHENCICATION_SUCCESS_CHART_LABEL = i18n.translate( +export const AUTHENTICATION_SUCCESS_CHART_LABEL = i18n.translate( 'xpack.securitySolution.visualizationActions.userAuthentications.authentication.successChartLabel', { defaultMessage: 'Success', @@ -81,7 +81,7 @@ export const FAIL_CHART_LABEL = i18n.translate( } ); -export const AUTHENCICATION_FAILURE_CHART_LABEL = i18n.translate( +export const AUTHENTICATION_FAILURE_CHART_LABEL = i18n.translate( 'xpack.securitySolution.visualizationActions.userAuthentications.authentication.failureChartLabel', { defaultMessage: 'Failure', @@ -111,3 +111,10 @@ export const COUNT_OF = (field: string) => values: { field }, defaultMessage: 'Count of {field}', }); + +export const ADDED_TO_LIBRARY = i18n.translate( + 'xpack.securitySolution.visualizationActions.addedToLibrary', + { + defaultMessage: 'Added to library', + } +); diff --git a/x-pack/plugins/security_solution/public/common/components/visualization_actions/use_actions.test.tsx b/x-pack/plugins/security_solution/public/common/components/visualization_actions/use_actions.test.tsx index 0de49b52d66ff..273e4d89d1d7a 100644 --- a/x-pack/plugins/security_solution/public/common/components/visualization_actions/use_actions.test.tsx +++ b/x-pack/plugins/security_solution/public/common/components/visualization_actions/use_actions.test.tsx @@ -6,9 +6,13 @@ */ import { renderHook } from '@testing-library/react-hooks'; +import React from 'react'; +import { NavigationProvider } from '@kbn/security-solution-navigation'; import { useKibana } from '../../lib/kibana/kibana_react'; import { mockAttributes } from './mocks'; import { useActions } from './use_actions'; +import { coreMock } from '@kbn/core/public/mocks'; +import { TestProviders } from '../../mock'; jest.mock('./use_add_to_existing_case', () => { return { @@ -32,6 +36,12 @@ jest.mock('../../lib/kibana/kibana_react', () => { }; }); +const coreStart = coreMock.createStart(); +const wrapper = ({ children }: { children: React.ReactNode }) => ( + + {children} + +); describe(`useActions`, () => { const mockNavigateToPrefilledEditor = jest.fn(); beforeAll(() => { @@ -39,6 +49,15 @@ describe(`useActions`, () => { services: { lens: { navigateToPrefilledEditor: mockNavigateToPrefilledEditor, + canUseEditor: jest.fn().mockReturnValue(true), + SaveModalComponent: jest + .fn() + .mockReturnValue(() =>
    ), + }, + notifications: { + toasts: { + addWarning: jest.fn(), + }, }, }, }); @@ -49,29 +68,34 @@ describe(`useActions`, () => { }); it('should render actions', () => { - const { result } = renderHook(() => - useActions({ - withActions: true, - attributes: mockAttributes, - timeRange: { - from: '2022-10-26T23:00:00.000Z', - to: '2022-11-03T15:16:50.053Z', - }, - inspectActionProps: { - onInspectActionClicked: jest.fn(), - isDisabled: false, - }, - }) + const { result } = renderHook( + () => + useActions({ + withActions: true, + attributes: mockAttributes, + timeRange: { + from: '2022-10-26T23:00:00.000Z', + to: '2022-11-03T15:16:50.053Z', + }, + inspectActionProps: { + onInspectActionClicked: jest.fn(), + isDisabled: false, + }, + }), + { + wrapper, + } ); - expect(result.current[0].id).toEqual('inspect'); expect(result.current[0].order).toEqual(4); expect(result.current[1].id).toEqual('addToNewCase'); expect(result.current[1].order).toEqual(3); expect(result.current[2].id).toEqual('addToExistingCase'); expect(result.current[2].order).toEqual(2); - expect(result.current[3].id).toEqual('openInLens'); + expect(result.current[3].id).toEqual('saveToLibrary'); expect(result.current[3].order).toEqual(1); + expect(result.current[4].id).toEqual('openInLens'); + expect(result.current[4].order).toEqual(0); }); it('should render extra actions if available', () => { @@ -92,31 +116,37 @@ describe(`useActions`, () => { order: 0, }, ]; - const { result } = renderHook(() => - useActions({ - withActions: true, - attributes: mockAttributes, - timeRange: { - from: '2022-10-26T23:00:00.000Z', - to: '2022-11-03T15:16:50.053Z', - }, - inspectActionProps: { - onInspectActionClicked: jest.fn(), - isDisabled: false, - }, - extraActions: mockExtraAction, - }) + const { result } = renderHook( + () => + useActions({ + withActions: true, + attributes: mockAttributes, + timeRange: { + from: '2022-10-26T23:00:00.000Z', + to: '2022-11-03T15:16:50.053Z', + }, + inspectActionProps: { + onInspectActionClicked: jest.fn(), + isDisabled: false, + }, + extraActions: mockExtraAction, + }), + { + wrapper, + } ); expect(result.current[0].id).toEqual('inspect'); - expect(result.current[0].order).toEqual(4); + expect(result.current[0].order).toEqual(5); expect(result.current[1].id).toEqual('addToNewCase'); - expect(result.current[1].order).toEqual(3); + expect(result.current[1].order).toEqual(4); expect(result.current[2].id).toEqual('addToExistingCase'); - expect(result.current[2].order).toEqual(2); - expect(result.current[3].id).toEqual('openInLens'); - expect(result.current[3].order).toEqual(1); - expect(result.current[4].id).toEqual('mockExtraAction'); - expect(result.current[4].order).toEqual(0); + expect(result.current[2].order).toEqual(3); + expect(result.current[3].id).toEqual('saveToLibrary'); + expect(result.current[3].order).toEqual(2); + expect(result.current[4].id).toEqual('openInLens'); + expect(result.current[4].order).toEqual(1); + expect(result.current[5].id).toEqual('mockExtraAction'); + expect(result.current[5].order).toEqual(0); }); }); diff --git a/x-pack/plugins/security_solution/public/common/components/visualization_actions/use_actions.ts b/x-pack/plugins/security_solution/public/common/components/visualization_actions/use_actions.ts index 08f8cd63f7673..760d9e396584e 100644 --- a/x-pack/plugins/security_solution/public/common/components/visualization_actions/use_actions.ts +++ b/x-pack/plugins/security_solution/public/common/components/visualization_actions/use_actions.ts @@ -10,8 +10,14 @@ import type { Action, ActionExecutionContext } from '@kbn/ui-actions-plugin/publ import { useKibana } from '../../lib/kibana/kibana_react'; import { useAddToExistingCase } from './use_add_to_existing_case'; import { useAddToNewCase } from './use_add_to_new_case'; +import { useSaveToLibrary } from './use_save_to_library'; -import { ADD_TO_EXISTING_CASE, ADD_TO_NEW_CASE, OPEN_IN_LENS } from './translations'; +import { + ADDED_TO_LIBRARY, + ADD_TO_EXISTING_CASE, + ADD_TO_NEW_CASE, + OPEN_IN_LENS, +} from './translations'; import type { LensAttributes } from './types'; import { INSPECT } from '../inspect/translations'; @@ -36,6 +42,7 @@ export const useActions = ({ 'inspect', 'addToNewCase', 'addToExistingCase', + 'saveToLibrary', 'openInLens', ]); @@ -72,6 +79,7 @@ export const useActions = ({ lensAttributes: attributes, }); + const { openSaveVisualizationFlyout, disableVisualizations } = useSaveToLibrary({ attributes }); const actions = useMemo( () => defaultActions?.reduce((acc, action) => { @@ -106,6 +114,16 @@ export const useActions = ({ return [...acc, getOpenInLensAction({ callback: onOpenInLens })]; } + if (action === 'saveToLibrary') { + return [ + ...acc, + getSaveToLibraryAction({ + callback: openSaveVisualizationFlyout, + disabled: disableVisualizations, + }), + ]; + } + return acc; }, []), [ @@ -116,10 +134,18 @@ export const useActions = ({ onAddToNewCaseClicked, isAddToNewCaseDisabled, onOpenInLens, + openSaveVisualizationFlyout, + disableVisualizations, ] ); - const withExtraActions = actions.concat(extraActions ?? []); + const withExtraActions = actions.concat(extraActions ?? []).map((a, i, totalActions) => { + const order = Math.max(totalActions.length - (1 + i), 0); + return { + ...a, + order, + }; + }); return withExtraActions; }; @@ -141,11 +167,38 @@ const getOpenInLensAction = ({ callback }: { callback: () => void }): Action => async execute(context: ActionExecutionContext): Promise { callback(); }, + order: 0, + }; +}; + +const getSaveToLibraryAction = ({ + callback, + disabled, +}: { + callback: () => void; + disabled?: boolean; +}): Action => { + return { + id: 'saveToLibrary', + getDisplayName(context: ActionExecutionContext): string { + return ADDED_TO_LIBRARY; + }, + getIconType(context: ActionExecutionContext): string | undefined { + return 'save'; + }, + type: 'actionButton', + async isCompatible(context: ActionExecutionContext): Promise { + return true; + }, + async execute(context: ActionExecutionContext): Promise { + callback(); + }, + disabled, order: 1, }; }; -const getAddToNewCaseAction = ({ +const getAddToExistingCaseAction = ({ callback, disabled, }: { @@ -153,9 +206,9 @@ const getAddToNewCaseAction = ({ disabled?: boolean; }): Action => { return { - id: 'addToNewCase', + id: 'addToExistingCase', getDisplayName(context: ActionExecutionContext): string { - return ADD_TO_NEW_CASE; + return ADD_TO_EXISTING_CASE; }, getIconType(context: ActionExecutionContext): string | undefined { return 'casesApp'; @@ -168,11 +221,11 @@ const getAddToNewCaseAction = ({ callback(); }, disabled, - order: 3, + order: 2, }; }; -const getInspectAction = ({ +const getAddToNewCaseAction = ({ callback, disabled, }: { @@ -180,12 +233,12 @@ const getInspectAction = ({ disabled?: boolean; }): Action => { return { - id: 'inspect', + id: 'addToNewCase', getDisplayName(context: ActionExecutionContext): string { - return INSPECT; + return ADD_TO_NEW_CASE; }, getIconType(context: ActionExecutionContext): string | undefined { - return 'inspect'; + return 'casesApp'; }, type: 'actionButton', async isCompatible(context: ActionExecutionContext): Promise { @@ -195,11 +248,11 @@ const getInspectAction = ({ callback(); }, disabled, - order: 4, + order: 3, }; }; -const getAddToExistingCaseAction = ({ +const getInspectAction = ({ callback, disabled, }: { @@ -207,12 +260,12 @@ const getAddToExistingCaseAction = ({ disabled?: boolean; }): Action => { return { - id: 'addToExistingCase', + id: 'inspect', getDisplayName(context: ActionExecutionContext): string { - return ADD_TO_EXISTING_CASE; + return INSPECT; }, getIconType(context: ActionExecutionContext): string | undefined { - return 'casesApp'; + return 'inspect'; }, type: 'actionButton', async isCompatible(context: ActionExecutionContext): Promise { @@ -222,6 +275,6 @@ const getAddToExistingCaseAction = ({ callback(); }, disabled, - order: 2, + order: 4, }; }; diff --git a/x-pack/plugins/security_solution/public/common/components/visualization_actions/use_redirect_to_dashboard_from_lens.ts b/x-pack/plugins/security_solution/public/common/components/visualization_actions/use_redirect_to_dashboard_from_lens.ts new file mode 100644 index 0000000000000..1aebf72217c5b --- /dev/null +++ b/x-pack/plugins/security_solution/public/common/components/visualization_actions/use_redirect_to_dashboard_from_lens.ts @@ -0,0 +1,59 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { useMemo, useCallback } from 'react'; +import { SecurityPageName } from '../../../../common'; +import { useNavigateTo } from '../../lib/kibana'; +import type { GetSecuritySolutionUrl } from '../link_to'; + +export const useRedirectToDashboardFromLens = ({ + getSecuritySolutionUrl, +}: { + getSecuritySolutionUrl: GetSecuritySolutionUrl; +}) => { + const { navigateTo } = useNavigateTo(); + + const dashboardListingUrl = useMemo( + () => + `${getSecuritySolutionUrl({ + deepLinkId: SecurityPageName.dashboards, + })}`, + [getSecuritySolutionUrl] + ); + + const getEditOrCreateDashboardPath = useCallback( + (id: string | null | undefined) => (id != null && id !== 'new' ? `${id}/edit` : `/create`), + [] + ); + const getEditOrCreateDashboardUrl = useCallback( + (id: string | null | undefined) => + `${getSecuritySolutionUrl({ + deepLinkId: SecurityPageName.dashboards, + path: getEditOrCreateDashboardPath(id), + })}`, + [getEditOrCreateDashboardPath, getSecuritySolutionUrl] + ); + + const redirectTo = useCallback( + (props) => { + if (props.destination === 'listing') { + navigateTo({ url: dashboardListingUrl }); + } + if (props.destination === 'dashboard') { + navigateTo({ url: getEditOrCreateDashboardUrl(props.id) }); + } + }, + [dashboardListingUrl, getEditOrCreateDashboardUrl, navigateTo] + ); + + return { + redirectTo, + getEditOrCreateDashboardPath, + getEditOrCreateDashboardUrl, + dashboardListingUrl, + }; +}; diff --git a/x-pack/plugins/security_solution/public/common/components/visualization_actions/use_save_to_library.tsx b/x-pack/plugins/security_solution/public/common/components/visualization_actions/use_save_to_library.tsx new file mode 100644 index 0000000000000..158b30979881a --- /dev/null +++ b/x-pack/plugins/security_solution/public/common/components/visualization_actions/use_save_to_library.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, { useCallback, useMemo } from 'react'; +import { toMountPoint } from '@kbn/react-kibana-mount'; +import type { LensEmbeddableInput } from '@kbn/lens-plugin/public'; +import { unmountComponentAtNode } from 'react-dom'; +import type { SaveProps } from '@kbn/lens-plugin/public/plugin'; +import { useKibana } from '../../lib/kibana'; +import type { LensAttributes } from './types'; +import { useRedirectToDashboardFromLens } from './use_redirect_to_dashboard_from_lens'; +import { APP_UI_ID, SecurityPageName } from '../../../../common'; +import { useGetSecuritySolutionUrl } from '../link_to'; + +export const useSaveToLibrary = ({ + attributes, +}: { + attributes: LensAttributes | undefined | null; +}) => { + const { lens, theme, i18n } = useKibana().services; + const { SaveModalComponent, canUseEditor } = lens; + const getSecuritySolutionUrl = useGetSecuritySolutionUrl(); + const { redirectTo, getEditOrCreateDashboardPath } = useRedirectToDashboardFromLens({ + getSecuritySolutionUrl, + }); + + const openSaveVisualizationFlyout = useCallback(() => { + const targetDomElement = document.createElement('div'); + const mount = toMountPoint( + { + unmountComponentAtNode(targetDomElement); + }} + onClose={() => { + unmountComponentAtNode(targetDomElement); + }} + originatingApp={APP_UI_ID} + getOriginatingPath={(dashboardId) => + `${SecurityPageName.dashboards}/${getEditOrCreateDashboardPath(dashboardId)}` + } + redirectTo={redirectTo} + />, + { theme, i18n } + ); + + mount(targetDomElement); + }, [SaveModalComponent, attributes, getEditOrCreateDashboardPath, i18n, redirectTo, theme]); + + const disableVisualizations = useMemo( + () => !canUseEditor() || attributes == null, + [attributes, canUseEditor] + ); + + return { openSaveVisualizationFlyout, disableVisualizations }; +}; diff --git a/x-pack/plugins/security_solution/public/common/store/inputs/selectors.ts b/x-pack/plugins/security_solution/public/common/store/inputs/selectors.ts index aee7d1957841d..b6ef6b0867504 100644 --- a/x-pack/plugins/security_solution/public/common/store/inputs/selectors.ts +++ b/x-pack/plugins/security_solution/public/common/store/inputs/selectors.ts @@ -13,6 +13,15 @@ import type { State } from '../types'; import type { InputsModel, InputsRange, GlobalQuery } from './model'; +const defaultQuery = { + id: 'kql', + inspect: null, + isInspected: false, + loading: false, + refetch: null, + selectedInspectIndex: 0, +}; + const selectInputs = (state: State): InputsModel => state.inputs; const selectGlobal = (state: State): InputsRange => state.inputs.global; @@ -24,25 +33,12 @@ const selectSocTrends = (state: State): InputsState['socTrends'] | undefined => state.inputs.socTrends; const selectGlobalQuery = (state: State, id: string): GlobalQuery => - state.inputs.global.queries.find((q) => q.id === id) || { - id: 'kql', - inspect: null, - isInspected: false, - loading: false, - refetch: null, - selectedInspectIndex: 0, - }; + state.inputs.global.queries.find((q) => q.id === id) || defaultQuery; const selectTimelineQuery = (state: State, id: string): GlobalQuery => state.inputs.timeline.queries.find((q) => q.id === id) || - state.inputs.global.queries.find((q) => q.id === id) || { - id: 'kql', - inspect: null, - isInspected: false, - loading: false, - refetch: null, - selectedInspectIndex: 0, - }; + state.inputs.global.queries.find((q) => q.id === id) || + defaultQuery; export const inputsSelector = () => createSelector(selectInputs, (inputs) => inputs); diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/model/coverage_overview/mitre_subtechnique.test.ts b/x-pack/plugins/security_solution/public/detection_engine/rule_management/model/coverage_overview/mitre_subtechnique.test.ts new file mode 100644 index 0000000000000..7129448e762cb --- /dev/null +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/model/coverage_overview/mitre_subtechnique.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 { CoverageOverviewRuleActivity } from '../../../../../common/api/detection_engine'; +import { getNumOfCoveredSubtechniques } from './mitre_subtechnique'; +import type { CoverageOverviewMitreTechnique } from './mitre_technique'; +import { + getMockCoverageOverviewMitreSubTechnique, + getMockCoverageOverviewMitreTechnique, +} from './__mocks__'; + +describe('mitre_subtechniques', () => { + describe('getNumOfCoveredSubtechniques', () => { + it('returns 0 when no subtechniques are present', () => { + const payload: CoverageOverviewMitreTechnique = getMockCoverageOverviewMitreTechnique(); + expect(getNumOfCoveredSubtechniques(payload)).toEqual(0); + }); + + it('returns total number of unique enabled and disabled subtechniques when no filter is passed', () => { + const payload: CoverageOverviewMitreTechnique = { + ...getMockCoverageOverviewMitreTechnique(), + subtechniques: [ + getMockCoverageOverviewMitreSubTechnique(), + { ...getMockCoverageOverviewMitreSubTechnique(), id: 'test-id' }, + ], + }; + expect(getNumOfCoveredSubtechniques(payload)).toEqual(2); + }); + + it('returns total number of unique enabled and disabled subtechniques when both filters are passed', () => { + const payload: CoverageOverviewMitreTechnique = { + ...getMockCoverageOverviewMitreTechnique(), + subtechniques: [ + getMockCoverageOverviewMitreSubTechnique(), + { ...getMockCoverageOverviewMitreSubTechnique(), id: 'test-id' }, + ], + }; + expect( + getNumOfCoveredSubtechniques(payload, [ + CoverageOverviewRuleActivity.Enabled, + CoverageOverviewRuleActivity.Disabled, + ]) + ).toEqual(2); + }); + + it('returns total number of enabled subtechniques when enabled filter is passed', () => { + const payload: CoverageOverviewMitreTechnique = { + ...getMockCoverageOverviewMitreTechnique(), + subtechniques: [ + { + ...getMockCoverageOverviewMitreSubTechnique(), + enabledRules: [], + }, + getMockCoverageOverviewMitreSubTechnique(), + ], + }; + expect(getNumOfCoveredSubtechniques(payload, [CoverageOverviewRuleActivity.Enabled])).toEqual( + 1 + ); + }); + + it('returns total number of disabled subtechniques when disabled filter is passed', () => { + const payload: CoverageOverviewMitreTechnique = { + ...getMockCoverageOverviewMitreTechnique(), + subtechniques: [ + { + ...getMockCoverageOverviewMitreSubTechnique(), + disabledRules: [], + }, + getMockCoverageOverviewMitreSubTechnique(), + ], + }; + expect( + getNumOfCoveredSubtechniques(payload, [CoverageOverviewRuleActivity.Disabled]) + ).toEqual(1); + }); + }); +}); diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/model/coverage_overview/mitre_subtechnique.ts b/x-pack/plugins/security_solution/public/detection_engine/rule_management/model/coverage_overview/mitre_subtechnique.ts index 622213c7e7a6f..0b0e8af2d8a99 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management/model/coverage_overview/mitre_subtechnique.ts +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/model/coverage_overview/mitre_subtechnique.ts @@ -5,6 +5,8 @@ * 2.0. */ +import { CoverageOverviewRuleActivity } from '../../../../../common/api/detection_engine'; +import type { CoverageOverviewMitreTechnique } from './mitre_technique'; import type { CoverageOverviewRule } from './rule'; export interface CoverageOverviewMitreSubTechnique { @@ -18,3 +20,26 @@ export interface CoverageOverviewMitreSubTechnique { disabledRules: CoverageOverviewRule[]; availableRules: CoverageOverviewRule[]; } + +export const getNumOfCoveredSubtechniques = ( + technique: CoverageOverviewMitreTechnique, + activity?: CoverageOverviewRuleActivity[] +): number => { + const coveredSubtechniques = new Set(); + for (const subtechnique of technique.subtechniques) { + if ( + (!activity || activity.includes(CoverageOverviewRuleActivity.Enabled)) && + subtechnique.enabledRules.length + ) { + coveredSubtechniques.add(subtechnique.id); + } + + if ( + (!activity || activity.includes(CoverageOverviewRuleActivity.Disabled)) && + subtechnique.disabledRules.length + ) { + coveredSubtechniques.add(subtechnique.id); + } + } + return coveredSubtechniques.size; +}; diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/model/coverage_overview/mitre_technique.test.ts b/x-pack/plugins/security_solution/public/detection_engine/rule_management/model/coverage_overview/mitre_technique.test.ts index 01794b34c8ee7..9a89867225ba8 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management/model/coverage_overview/mitre_technique.test.ts +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/model/coverage_overview/mitre_technique.test.ts @@ -6,27 +6,52 @@ */ import { CoverageOverviewRuleActivity } from '../../../../../common/api/detection_engine'; -import { getTotalRuleCount } from './mitre_technique'; -import { getMockCoverageOverviewMitreTechnique } from './__mocks__'; +import type { CoverageOverviewMitreTactic } from './mitre_tactic'; +import type { CoverageOverviewMitreTechnique } from './mitre_technique'; +import { getNumOfCoveredTechniques, getTotalRuleCount } from './mitre_technique'; +import { + getMockCoverageOverviewMitreTactic, + getMockCoverageOverviewMitreTechnique, +} from './__mocks__'; -describe('getTotalRuleCount', () => { - it('returns count of all rules when no activity filter is present', () => { - const payload = getMockCoverageOverviewMitreTechnique(); - expect(getTotalRuleCount(payload)).toEqual(2); - }); +describe('mitre_technique', () => { + describe('getTotalRuleCount', () => { + it('returns count of all rules when no activity filter is present', () => { + const payload: CoverageOverviewMitreTechnique = getMockCoverageOverviewMitreTechnique(); + expect(getTotalRuleCount(payload)).toEqual(2); + }); + + it('returns count of one rule type when an activity filter is present', () => { + const payload: CoverageOverviewMitreTechnique = getMockCoverageOverviewMitreTechnique(); + expect(getTotalRuleCount(payload, [CoverageOverviewRuleActivity.Disabled])).toEqual(1); + }); - it('returns count of one rule type when an activity filter is present', () => { - const payload = getMockCoverageOverviewMitreTechnique(); - expect(getTotalRuleCount(payload, [CoverageOverviewRuleActivity.Disabled])).toEqual(1); + it('returns count of multiple rule type when multiple activity filter is present', () => { + const payload = getMockCoverageOverviewMitreTechnique(); + expect( + getTotalRuleCount(payload, [ + CoverageOverviewRuleActivity.Enabled, + CoverageOverviewRuleActivity.Disabled, + ]) + ).toEqual(2); + }); }); - it('returns count of multiple rule type when multiple activity filter is present', () => { - const payload = getMockCoverageOverviewMitreTechnique(); - expect( - getTotalRuleCount(payload, [ - CoverageOverviewRuleActivity.Enabled, - CoverageOverviewRuleActivity.Disabled, - ]) - ).toEqual(2); + describe('getNumOfCoveredTechniques', () => { + it('returns 0 when no techniques are present', () => { + const payload: CoverageOverviewMitreTactic = getMockCoverageOverviewMitreTactic(); + expect(getNumOfCoveredTechniques(payload)).toEqual(0); + }); + + it('returns number of techniques when present', () => { + const payload: CoverageOverviewMitreTactic = { + ...getMockCoverageOverviewMitreTactic(), + techniques: [ + getMockCoverageOverviewMitreTechnique(), + getMockCoverageOverviewMitreTechnique(), + ], + }; + expect(getNumOfCoveredTechniques(payload)).toEqual(2); + }); }); }); diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/model/coverage_overview/mitre_technique.ts b/x-pack/plugins/security_solution/public/detection_engine/rule_management/model/coverage_overview/mitre_technique.ts index 589629d643810..23f57497d7d7d 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management/model/coverage_overview/mitre_technique.ts +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/model/coverage_overview/mitre_technique.ts @@ -7,6 +7,7 @@ import { CoverageOverviewRuleActivity } from '../../../../../common/api/detection_engine'; import type { CoverageOverviewMitreSubTechnique } from './mitre_subtechnique'; +import type { CoverageOverviewMitreTactic } from './mitre_tactic'; import type { CoverageOverviewRule } from './rule'; export interface CoverageOverviewMitreTechnique { @@ -38,3 +39,6 @@ export const getTotalRuleCount = ( } return totalRuleCount; }; + +export const getNumOfCoveredTechniques = (tactic: CoverageOverviewMitreTactic): number => + tactic.techniques.filter((technique) => technique.enabledRules.length !== 0).length; diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/pages/coverage_overview/helpers.test.ts b/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/pages/coverage_overview/helpers.test.ts index 5a1aee424352a..39e0b9d7bbb53 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/pages/coverage_overview/helpers.test.ts +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/pages/coverage_overview/helpers.test.ts @@ -7,56 +7,10 @@ import type { CoverageOverviewRuleActivity } from '../../../../../common/api/detection_engine'; import { getCoverageOverviewFilterMock } from '../../../../../common/api/detection_engine/rule_management/coverage_overview/coverage_overview_route.mock'; -import { - getMockCoverageOverviewMitreSubTechnique, - getMockCoverageOverviewMitreTactic, - getMockCoverageOverviewMitreTechnique, -} from '../../../rule_management/model/coverage_overview/__mocks__'; import { ruleActivityFilterDefaultOptions } from './constants'; -import { - extractSelected, - getNumOfCoveredSubtechniques, - getNumOfCoveredTechniques, - populateSelected, -} from './helpers'; +import { extractSelected, populateSelected } from './helpers'; describe('helpers', () => { - describe('getNumOfCoveredTechniques', () => { - it('returns 0 when no techniques are present', () => { - const payload = getMockCoverageOverviewMitreTactic(); - expect(getNumOfCoveredTechniques(payload)).toEqual(0); - }); - - it('returns number of techniques when present', () => { - const payload = { - ...getMockCoverageOverviewMitreTactic(), - techniques: [ - getMockCoverageOverviewMitreTechnique(), - getMockCoverageOverviewMitreTechnique(), - ], - }; - expect(getNumOfCoveredTechniques(payload)).toEqual(2); - }); - }); - - describe('getNumOfCoveredSubtechniques', () => { - it('returns 0 when no subtechniques are present', () => { - const payload = getMockCoverageOverviewMitreTechnique(); - expect(getNumOfCoveredSubtechniques(payload)).toEqual(0); - }); - - it('returns number of subtechniques when present', () => { - const payload = { - ...getMockCoverageOverviewMitreTechnique(), - subtechniques: [ - getMockCoverageOverviewMitreSubTechnique(), - getMockCoverageOverviewMitreSubTechnique(), - ], - }; - expect(getNumOfCoveredSubtechniques(payload)).toEqual(2); - }); - }); - describe('extractSelected', () => { it('returns empty array when no options are checked', () => { const payload = ruleActivityFilterDefaultOptions; diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/pages/coverage_overview/helpers.ts b/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/pages/coverage_overview/helpers.ts index 82d50e7b9721b..ecd67546e7627 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/pages/coverage_overview/helpers.ts +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/pages/coverage_overview/helpers.ts @@ -10,16 +10,8 @@ import type { CoverageOverviewRuleActivity, CoverageOverviewRuleSource, } from '../../../../../common/api/detection_engine'; -import type { CoverageOverviewMitreTactic } from '../../../rule_management/model/coverage_overview/mitre_tactic'; -import type { CoverageOverviewMitreTechnique } from '../../../rule_management/model/coverage_overview/mitre_technique'; import { coverageOverviewCardColorThresholds } from './constants'; -export const getNumOfCoveredTechniques = (tactic: CoverageOverviewMitreTactic): number => - tactic.techniques.filter((technique) => technique.enabledRules.length !== 0).length; - -export const getNumOfCoveredSubtechniques = (technique: CoverageOverviewMitreTechnique): number => - technique.subtechniques.filter((subtechnique) => subtechnique.enabledRules.length !== 0).length; - export const getCardBackgroundColor = (value: number) => { for (const { threshold, color } of coverageOverviewCardColorThresholds) { if (value >= threshold) { diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/pages/coverage_overview/tactic_panel.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/pages/coverage_overview/tactic_panel.tsx index e1d1749ca264f..64ef73c8259c9 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/pages/coverage_overview/tactic_panel.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/pages/coverage_overview/tactic_panel.tsx @@ -11,9 +11,9 @@ import React, { memo, useMemo } from 'react'; import { euiThemeVars } from '@kbn/ui-theme'; import type { CoverageOverviewMitreTactic } from '../../../rule_management/model/coverage_overview/mitre_tactic'; import { coverageOverviewPanelWidth } from './constants'; -import { getNumOfCoveredTechniques } from './helpers'; import * as i18n from './translations'; import { CoverageOverviewPanelRuleStats } from './shared_components/panel_rule_stats'; +import { getNumOfCoveredTechniques } from '../../../rule_management/model/coverage_overview/mitre_technique'; export interface CoverageOverviewTacticPanelProps { tactic: CoverageOverviewMitreTactic; diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/pages/coverage_overview/technique_panel_popover.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/pages/coverage_overview/technique_panel_popover.tsx index f5fc71b08b055..9e026e9912b46 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/pages/coverage_overview/technique_panel_popover.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/pages/coverage_overview/technique_panel_popover.tsx @@ -23,12 +23,12 @@ import { css, cx } from '@emotion/css'; import React, { memo, useCallback, useMemo, useState } from 'react'; import { useUserData } from '../../../../detections/components/user_info'; import type { CoverageOverviewMitreTechnique } from '../../../rule_management/model/coverage_overview/mitre_technique'; -import { getNumOfCoveredSubtechniques } from './helpers'; import { CoverageOverviewRuleListHeader } from './shared_components/popover_list_header'; import { CoverageOverviewMitreTechniquePanel } from './technique_panel'; import * as i18n from './translations'; import { RuleLink } from '../../components/rules_table/use_columns'; import { useCoverageOverviewDashboardContext } from './coverage_overview_dashboard_context'; +import { getNumOfCoveredSubtechniques } from '../../../rule_management/model/coverage_overview/mitre_subtechnique'; export interface CoverageOverviewMitreTechniquePanelPopoverProps { technique: CoverageOverviewMitreTechnique; @@ -41,7 +41,6 @@ const CoverageOverviewMitreTechniquePanelPopoverComponent = ({ const [isPopoverOpen, setIsPopoverOpen] = useState(false); const [isLoading, setIsLoading] = useState(false); const closePopover = useCallback(() => setIsPopoverOpen(false), []); - const coveredSubtechniques = useMemo(() => getNumOfCoveredSubtechniques(technique), [technique]); const isEnableButtonDisabled = useMemo( () => !canUserCRUD || technique.disabledRules.length === 0, [canUserCRUD, technique.disabledRules.length] @@ -53,10 +52,18 @@ const CoverageOverviewMitreTechniquePanelPopoverComponent = ({ ); const { - state: { showExpandedCells }, + state: { + showExpandedCells, + filter: { activity }, + }, actions: { enableAllDisabled }, } = useCoverageOverviewDashboardContext(); + const coveredSubtechniques = useMemo( + () => getNumOfCoveredSubtechniques(technique, activity), + [activity, technique] + ); + const handleEnableAllDisabled = useCallback(async () => { setIsLoading(true); const ruleIds = technique.disabledRules.map((rule) => rule.id); 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 cb20b7910a929..741039c09e0e2 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 @@ -9,8 +9,7 @@ import React, { useCallback, useMemo, useState } from 'react'; import { EuiButtonIcon, EuiContextMenu, EuiPopover, EuiToolTip } from '@elastic/eui'; import { indexOf } from 'lodash'; -import type { ConnectedProps } from 'react-redux'; -import { connect } from 'react-redux'; +import { useSelector } from 'react-redux'; import { ExceptionListTypeEnum } from '@kbn/securitysolution-io-ts-list-types'; import { get } from 'lodash/fp'; import type { EcsSecurityExtension as Ecs } from '@kbn/securitysolution-ecs'; @@ -63,7 +62,7 @@ interface AlertContextMenuProps { refetch: (() => void) | undefined; } -const AlertContextMenuComponent: React.FC = ({ +const AlertContextMenuComponent: React.FC = ({ ariaLabel = i18n.MORE_ACTIONS, ariaRowindex, columnValues, @@ -71,8 +70,6 @@ const AlertContextMenuComponent: React.FC { const [isPopoverOpen, setPopover] = useState(false); @@ -82,6 +79,11 @@ const AlertContextMenuComponent: React.FC inputsSelectors.globalQuery(), []); + const getTimelineQuery = useMemo(() => inputsSelectors.timelineQueryByIdSelector(), []); + const globalQuery = useSelector((state: State) => getGlobalQueries(state)); + const timelineQuery = useSelector((state: State) => getTimelineQuery(state, scopeId)); + const getAlertId = () => (ecsRowData?.kibana?.alert ? ecsRowData?._id : null); const alertId = getAlertId(); const ruleId = get(0, ecsRowData?.kibana?.alert?.rule?.uuid); @@ -323,23 +325,7 @@ const AlertContextMenuComponent: React.FC { - const getGlobalQueries = inputsSelectors.globalQuery(); - const getTimelineQuery = inputsSelectors.timelineQueryByIdSelector(); - const mapStateToProps = (state: State, { scopeId }: AlertContextMenuProps) => { - return { - globalQuery: getGlobalQueries(state), - timelineQuery: getTimelineQuery(state, scopeId), - }; - }; - return mapStateToProps; -}; - -const connector = connect(makeMapStateToProps); - -type PropsFromRedux = ConnectedProps; - -export const AlertContextMenu = connector(React.memo(AlertContextMenuComponent)); +export const AlertContextMenu = React.memo(AlertContextMenuComponent); type AddExceptionFlyoutWrapperProps = Omit< AddExceptionFlyoutProps, diff --git a/x-pack/plugins/security_solution/public/flyout/README.md b/x-pack/plugins/security_solution/public/flyout/README.md index dbce8ba6fad18..be70c3ca0ebec 100644 --- a/x-pack/plugins/security_solution/public/flyout/README.md +++ b/x-pack/plugins/security_solution/public/flyout/README.md @@ -56,6 +56,7 @@ Here's a non-exhaustive list of the reusable component in the top-level `shared` - [FlyoutNavigation](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/flyout/shared/components/flyout_navigation.tsx): navigation menu on the **right panel** only, with expand/collapse button and option to pass in a list of actions to be displayed on top. Works best when used in combination with the header component below. - [FlyoutHeader](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/flyout/shared/components/flyout_header.tsx): wrapper of `EuiFlyoutHeader`, setting the recommended `16px` padding using a EuiPanel. + - [FlyoutTitle](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/flyout/shared/components/flyout_title.tsx): title component with optional icon to indicate the type of document, works when the title is link or pure text - [FlyoutHeaderTabs](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/flyout/shared/components/flyout_header_tabs.tsx): Wrapper of `EuiTabs`, setting bottom margin to align with the flyout header divider - [FlyoutBody](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/flyout/shared/components/flyout_body.tsx): wrapper of `EuiFlyoutHeader`, setting the recommended `16px` padding using a EuiPanel. - [FlyoutFooter](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/flyout/shared/components/flyout_footer.tsx): wrapper of `EuiFlyoutFooter`, setting the recommended `16px` padding using a EuiPanel. diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/left/components/host_details.tsx b/x-pack/plugins/security_solution/public/flyout/document_details/left/components/host_details.tsx index bdfb03639382c..3f68ef15956ed 100644 --- a/x-pack/plugins/security_solution/public/flyout/document_details/left/components/host_details.tsx +++ b/x-pack/plugins/security_solution/public/flyout/document_details/left/components/host_details.tsx @@ -195,7 +195,7 @@ export const HostDetails: React.FC = ({ hostName, timestamp, s const relatedUsersCount = useMemo( () => ( - + diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/left/components/user_details.tsx b/x-pack/plugins/security_solution/public/flyout/document_details/left/components/user_details.tsx index daa58fc4d0379..1758bbc5b05d8 100644 --- a/x-pack/plugins/security_solution/public/flyout/document_details/left/components/user_details.tsx +++ b/x-pack/plugins/security_solution/public/flyout/document_details/left/components/user_details.tsx @@ -196,7 +196,7 @@ export const UserDetails: React.FC = ({ userName, timestamp, s const relatedHostsCount = useMemo( () => ( - + diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/preview/components/rule_preview.tsx b/x-pack/plugins/security_solution/public/flyout/document_details/preview/components/rule_preview.tsx index 6e4d9221421ee..6f679df0c5e9e 100644 --- a/x-pack/plugins/security_solution/public/flyout/document_details/preview/components/rule_preview.tsx +++ b/x-pack/plugins/security_solution/public/flyout/document_details/preview/components/rule_preview.tsx @@ -34,6 +34,14 @@ const panelViewStyle = css` font-size: 90% !important; } text-overflow: ellipsis; + .euiFlexGroup { + flex-wrap: inherit; + } + + .euiFlexItem { + inline-size: inherit; + flex-basis: inherit; + } `; /** diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/right/components/description.tsx b/x-pack/plugins/security_solution/public/flyout/document_details/right/components/description.tsx index 105d57ba4e7f6..0003a5cd2c123 100644 --- a/x-pack/plugins/security_solution/public/flyout/document_details/right/components/description.tsx +++ b/x-pack/plugins/security_solution/public/flyout/document_details/right/components/description.tsx @@ -98,7 +98,12 @@ export const Description: FC = () => { {isAlert ? ( - +
    { data-test-subj={INSIGHTS_ENTITIES_TEST_ID} > {userName || hostName ? ( - + {userName && ( diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/right/components/header_actions.test.tsx b/x-pack/plugins/security_solution/public/flyout/document_details/right/components/header_actions.test.tsx index e7a7d769b5702..ec7f85be212c9 100644 --- a/x-pack/plugins/security_solution/public/flyout/document_details/right/components/header_actions.test.tsx +++ b/x-pack/plugins/security_solution/public/flyout/document_details/right/components/header_actions.test.tsx @@ -10,8 +10,9 @@ import { render, fireEvent } from '@testing-library/react'; import { ExpandableFlyoutContext } from '@kbn/expandable-flyout/src/context'; import { copyToClipboard } from '@elastic/eui'; import { RightPanelContext } from '../context'; -import { SHARE_BUTTON_TEST_ID } from './test_ids'; +import { SHARE_BUTTON_TEST_ID, CHAT_BUTTON_TEST_ID } from './test_ids'; import { HeaderActions } from './header_actions'; +import { useAssistant } from '../hooks/use_assistant'; import { mockGetFieldsData } from '../../shared/mocks/mock_get_fields_data'; import { mockDataFormattedForFieldBrowser } from '../../shared/mocks/mock_data_formatted_for_field_browser'; import { TestProvidersComponent } from '../../../../common/mock'; @@ -19,6 +20,7 @@ import { useGetAlertDetailsFlyoutLink } from '../../../../timelines/components/s import { FLYOUT_URL_PARAM } from '../../shared/hooks/url/use_sync_flyout_state_with_url'; jest.mock('../../../../common/lib/kibana'); +jest.mock('../hooks/use_assistant'); jest.mock( '../../../../timelines/components/side_panel/event_details/use_get_alert_details_flyout_link' ); @@ -50,6 +52,7 @@ const renderHeaderActions = (contextValue: RightPanelContext) => describe('', () => { beforeEach(() => { jest.mocked(useGetAlertDetailsFlyoutLink).mockReturnValue(alertUrl); + jest.mocked(useAssistant).mockReturnValue({ showAssistant: true, promptContextId: '' }); }); describe('Share alert url action', () => { @@ -87,5 +90,19 @@ describe('', () => { }); expect(queryByTestId(SHARE_BUTTON_TEST_ID)).not.toBeInTheDocument(); }); + + it('should render chat button in the title', () => { + const { getByTestId } = renderHeaderActions(mockContextValue); + + expect(getByTestId(CHAT_BUTTON_TEST_ID)).toBeInTheDocument(); + }); + + it('should not render chat button in the title if should not be shown', () => { + jest.mocked(useAssistant).mockReturnValue({ showAssistant: false, promptContextId: '' }); + + const { queryByTestId } = renderHeaderActions(mockContextValue); + + expect(queryByTestId(CHAT_BUTTON_TEST_ID)).not.toBeInTheDocument(); + }); }); }); diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/right/components/header_actions.tsx b/x-pack/plugins/security_solution/public/flyout/document_details/right/components/header_actions.tsx index 0b60555b28f15..2862aed53501b 100644 --- a/x-pack/plugins/security_solution/public/flyout/document_details/right/components/header_actions.tsx +++ b/x-pack/plugins/security_solution/public/flyout/document_details/right/components/header_actions.tsx @@ -7,12 +7,18 @@ import type { VFC } from 'react'; import React, { memo } from 'react'; -import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; +import { EuiButtonIcon, EuiCopy, EuiFlexGroup, EuiFlexItem, EuiToolTip } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; +import { NewChatById } from '@kbn/elastic-assistant'; +import { copyFunction } from '../../../shared/utils/copy_to_clipboard'; import { FLYOUT_URL_PARAM } from '../../shared/hooks/url/use_sync_flyout_state_with_url'; -import { CopyToClipboard } from '../../../shared/components/copy_to_clipboard'; import { useGetAlertDetailsFlyoutLink } from '../../../../timelines/components/side_panel/event_details/use_get_alert_details_flyout_link'; import { useBasicDataFromDetailsData } from '../../../../timelines/components/side_panel/event_details/helpers'; +import { useAssistant } from '../hooks/use_assistant'; +import { + ALERT_SUMMARY_CONVERSATION_ID, + EVENT_SUMMARY_CONVERSATION_ID, +} from '../../../../common/components/event_details/translations'; import { useRightPanelContext } from '../context'; import { SHARE_BUTTON_TEST_ID } from './test_ids'; @@ -31,26 +37,57 @@ export const HeaderActions: VFC = memo(() => { const showShareAlertButton = isAlert && alertDetailsLink; + const modifier = (value: string) => { + const query = new URLSearchParams(window.location.search); + return `${value}&${FLYOUT_URL_PARAM}=${query.get(FLYOUT_URL_PARAM)}`; + }; + + const { showAssistant, promptContextId } = useAssistant({ + dataFormattedForFieldBrowser, + isAlert, + }); + return ( - + + {showAssistant && ( + + + + )} {showShareAlertButton && ( - { - const query = new URLSearchParams(window.location.search); - return `${value}&${FLYOUT_URL_PARAM}=${query.get(FLYOUT_URL_PARAM)}`; - }} - iconType={'share'} - color={'text'} - ariaLabel={i18n.translate( - 'xpack.securitySolution.flyout.right.header.shareButtonAriaLabel', - { - defaultMessage: 'Share Alert', - } + + > + + {(copy) => ( + copyFunction(copy, alertDetailsLink, modifier)} + onKeyDown={() => copyFunction(copy, alertDetailsLink, modifier)} + /> + )} + + )} diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/right/components/header_title.tsx b/x-pack/plugins/security_solution/public/flyout/document_details/right/components/header_title.tsx index b9e517a418893..1573f5ef33bcf 100644 --- a/x-pack/plugins/security_solution/public/flyout/document_details/right/components/header_title.tsx +++ b/x-pack/plugins/security_solution/public/flyout/document_details/right/components/header_title.tsx @@ -7,19 +7,9 @@ import type { FC } from 'react'; import React, { memo, useMemo } from 'react'; -import { - EuiFlexGroup, - EuiFlexItem, - EuiSpacer, - EuiTitle, - useEuiTheme, - EuiTextColor, - EuiIcon, - EuiToolTip, -} from '@elastic/eui'; +import { EuiFlexGroup, EuiFlexItem, EuiSpacer, EuiTitle } from '@elastic/eui'; import { isEmpty } from 'lodash'; import { FormattedMessage } from '@kbn/i18n-react'; -import { css } from '@emotion/react'; import { DocumentStatus } from './status'; import { DocumentSeverity } from './severity'; import { RiskScore } from './risk_score'; @@ -29,6 +19,7 @@ import { PreferenceFormattedDate } from '../../../../common/components/formatted import { RenderRuleName } from '../../../../timelines/components/timeline/body/renderers/formatted_field_helpers'; import { SIGNAL_RULE_NAME_FIELD_NAME } from '../../../../timelines/components/timeline/body/renderers/constants'; import { FLYOUT_HEADER_TITLE_TEST_ID } from './test_ids'; +import { FlyoutTitle } from '../../../shared/components/flyout_title'; /** * Document details flyout right section header @@ -38,55 +29,29 @@ export const HeaderTitle: FC = memo(() => { const { isAlert, ruleName, timestamp, ruleId } = useBasicDataFromDetailsData( dataFormattedForFieldBrowser ); - const { euiTheme } = useEuiTheme(); + const ruleTitle = useMemo( () => ( - - -
    - -   - - - {ruleName} - - -   - -
    -
    -
    + + + ), - [ruleName, ruleId, eventId, scopeId, euiTheme.colors.primaryText, euiTheme.size] + [ruleName, ruleId, eventId, scopeId] ); const eventTitle = ( @@ -108,7 +73,7 @@ export const HeaderTitle: FC = memo(() => { {isAlert && !isEmpty(ruleName) ? ruleTitle : eventTitle} - + diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/right/components/host_entity_overview.tsx b/x-pack/plugins/security_solution/public/flyout/document_details/right/components/host_entity_overview.tsx index fdc3edf96e9b8..58d9bf9d8a418 100644 --- a/x-pack/plugins/security_solution/public/flyout/document_details/right/components/host_entity_overview.tsx +++ b/x-pack/plugins/security_solution/public/flyout/document_details/right/components/host_entity_overview.tsx @@ -156,7 +156,7 @@ export const HostEntityOverview: React.FC = ({ hostName return [ { title: ( - + {HOST_RISK_LEVEL} @@ -177,9 +177,14 @@ export const HostEntityOverview: React.FC = ({ hostName }, [hostRisk]); return ( - + - + @@ -207,7 +212,7 @@ export const HostEntityOverview: React.FC = ({ hostName /> ) : ( - + = ({ const colorDataTestSubj = `${dataTestSubj}Color`; return ( - + - - - + data-test-subj={iconDataTestSubj} + aria-label={i18n.translate( + 'xpack.securitySolution.flyout.right.insights.insightSummaryButtonIconAriaLabel', + { + defaultMessage: 'Insight summary row icon', + } + )} + color="text" + display="empty" + type={icon} + size="m" + /> {
    {isAlert ? ( - - + +
    { } return ( - +

    diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/right/components/test_ids.ts b/x-pack/plugins/security_solution/public/flyout/document_details/right/components/test_ids.ts index 1140e8952aaff..28d76c040ebbb 100644 --- a/x-pack/plugins/security_solution/public/flyout/document_details/right/components/test_ids.ts +++ b/x-pack/plugins/security_solution/public/flyout/document_details/right/components/test_ids.ts @@ -17,6 +17,7 @@ export const SEVERITY_VALUE_TEST_ID = 'severity' as const; export const RISK_SCORE_TITLE_TEST_ID = `${FLYOUT_HEADER_TEST_ID}RiskScoreTitle` as const; export const RISK_SCORE_VALUE_TEST_ID = `${FLYOUT_HEADER_TEST_ID}RiskScoreValue` as const; export const SHARE_BUTTON_TEST_ID = `${FLYOUT_HEADER_TEST_ID}ShareButton` as const; +export const CHAT_BUTTON_TEST_ID = 'newChatById' as const; /* About section */ diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/right/components/user_entity_overview.tsx b/x-pack/plugins/security_solution/public/flyout/document_details/right/components/user_entity_overview.tsx index cd1a057b6fbc0..81b1b75df57e9 100644 --- a/x-pack/plugins/security_solution/public/flyout/document_details/right/components/user_entity_overview.tsx +++ b/x-pack/plugins/security_solution/public/flyout/document_details/right/components/user_entity_overview.tsx @@ -155,7 +155,7 @@ export const UserEntityOverview: React.FC = ({ userName return [ { title: ( - + {USER_RISK_LEVEL} @@ -176,9 +176,14 @@ export const UserEntityOverview: React.FC = ({ userName }, [userRisk]); return ( - + - + @@ -206,7 +211,7 @@ export const UserEntityOverview: React.FC = ({ userName data-test-subj={ENTITIES_USER_OVERVIEW_LOADING_TEST_ID} /> ) : ( - + { return ( - - } - iconType={'copyClipboard'} - size={'xs'} - ariaLabel={i18n.translate( - 'xpack.securitySolution.flyout.right.jsonTab.copyToClipboardButtonAriaLabel', - { - defaultMessage: 'Copy to clipboard', - } + + {(copy) => ( + copyFunction(copy, jsonValue)} + onKeyDown={() => copyFunction(copy, jsonValue)} + > + + )} - data-test-subj={JSON_TAB_COPY_TO_CLIPBOARD_BUTTON_TEST_ID} - /> + diff --git a/x-pack/plugins/security_solution/public/flyout/shared/components/copy_to_clipboard.stories.tsx b/x-pack/plugins/security_solution/public/flyout/shared/components/copy_to_clipboard.stories.tsx deleted file mode 100644 index 16519305d2a00..0000000000000 --- a/x-pack/plugins/security_solution/public/flyout/shared/components/copy_to_clipboard.stories.tsx +++ /dev/null @@ -1,125 +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 type { Story } from '@storybook/react'; -import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; -import { CopyToClipboard } from './copy_to_clipboard'; - -export default { - component: CopyToClipboard, - title: 'Flyout/CopyToClipboard', -}; - -const json = JSON.stringify({ - foo: 'bar', -}); - -export const Default: Story = () => { - return ( - {'Copy'}

    } - iconType={'copyClipboard'} - ariaLabel={'Copy'} - /> - ); -}; - -export const WithModifier: Story = () => { - return ( - { - window.alert('modifier'); - return value; - }} - text={

    {'Copy'}

    } - iconType={'copyClipboard'} - ariaLabel={'Copy'} - /> - ); -}; - -export const MultipleSizes: Story = () => { - return ( - - - {'xs size'}

    } - iconType={'copyClipboard'} - size={'xs'} - ariaLabel={'Copy'} - /> -
    - - {'s size'}

    } - iconType={'copyClipboard'} - size={'s'} - ariaLabel={'Copy'} - /> -
    - - {'m size'}

    } - iconType={'copyClipboard'} - size={'m'} - ariaLabel={'Copy'} - /> -
    -
    - ); -}; - -export const ButtonOnly: Story = () => { - return ( - { - window.alert('modifier'); - return value; - }} - iconType={'copyClipboard'} - ariaLabel={'Copy'} - /> - ); -}; - -export const CustomColor: Story = () => { - return ( - { - window.alert('modifier'); - return value; - }} - iconType={'copyClipboard'} - ariaLabel={'Copy'} - text={

    {'showing custom color'}

    } - color={'accent'} - /> - ); -}; - -export const CustomIcon: Story = () => { - return ( - { - window.alert('modifier'); - return value; - }} - iconType={'share'} - ariaLabel={'Share'} - text={

    {'custom icon'}

    } - /> - ); -}; diff --git a/x-pack/plugins/security_solution/public/flyout/shared/components/copy_to_clipboard.test.tsx b/x-pack/plugins/security_solution/public/flyout/shared/components/copy_to_clipboard.test.tsx deleted file mode 100644 index 1f9c5976f18a9..0000000000000 --- a/x-pack/plugins/security_solution/public/flyout/shared/components/copy_to_clipboard.test.tsx +++ /dev/null @@ -1,72 +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 { __IntlProvider as IntlProvider } from '@kbn/i18n-react'; -import { render } from '@testing-library/react'; -import React from 'react'; -import type { CopyToClipboardProps } from './copy_to_clipboard'; -import { CopyToClipboard } from './copy_to_clipboard'; - -jest.mock('@elastic/eui', () => ({ - ...jest.requireActual('@elastic/eui'), - copyToClipboard: jest.fn(), - EuiCopy: jest.fn(({ children: functionAsChild }) => functionAsChild(jest.fn())), -})); - -const renderShareButton = (props: CopyToClipboardProps) => - render( - - - - ); - -describe('ShareButton', () => { - beforeEach(() => { - jest.clearAllMocks(); - }); - - it('should render the copy to clipboard button', () => { - const text = 'text'; - - const props = { - rawValue: 'rawValue', - text: {text}, - iconType: 'iconType', - ariaLabel: 'ariaLabel', - 'data-test-subj': 'data-test-subj', - }; - const { getByTestId, getByText } = renderShareButton(props); - - const button = getByTestId('data-test-subj'); - - expect(button).toBeInTheDocument(); - expect(button).toHaveAttribute('aria-label', props.ariaLabel); - expect(button).toHaveAttribute('type', 'button'); - - expect(getByText(text)).toBeInTheDocument(); - }); - - it('should use modifier if provided', () => { - const modifiedFc = jest.fn(); - - const props = { - rawValue: 'rawValue', - modifier: modifiedFc, - text: {'text'}, - iconType: 'iconType', - ariaLabel: 'ariaLabel', - 'data-test-subj': 'data-test-subj', - }; - const { getByTestId } = renderShareButton(props); - - const button = getByTestId('data-test-subj'); - - button.click(); - - expect(modifiedFc).toHaveBeenCalledWith(props.rawValue); - }); -}); diff --git a/x-pack/plugins/security_solution/public/flyout/shared/components/copy_to_clipboard.tsx b/x-pack/plugins/security_solution/public/flyout/shared/components/copy_to_clipboard.tsx deleted file mode 100644 index 0727349543d8e..0000000000000 --- a/x-pack/plugins/security_solution/public/flyout/shared/components/copy_to_clipboard.tsx +++ /dev/null @@ -1,88 +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 { EuiButtonEmptyProps } from '@elastic/eui'; -import { copyToClipboard, EuiButtonEmpty, EuiCopy } from '@elastic/eui'; -import type { FC, ReactElement } from 'react'; -import React from 'react'; - -export interface CopyToClipboardProps { - /** - * Value to save to the clipboard - */ - rawValue: string; - /** - * Function to modify the raw value before saving to the clipboard - */ - modifier?: (rawValue: string) => string; - /** - * Button main text (next to icon) - */ - text?: ReactElement; - /** - * Icon name (value coming from EUI) - */ - iconType: EuiButtonEmptyProps['iconType']; - /** - * Button size (values coming from EUI) - */ - size?: EuiButtonEmptyProps['size']; - /** - * Optional button color - */ - color?: EuiButtonEmptyProps['color']; - /** - * Aria label value for the button - */ - ariaLabel: string; - /** - Data test subject string for testing - */ - ['data-test-subj']?: string; -} - -/** - * Copy to clipboard component - */ -export const CopyToClipboard: FC = ({ - rawValue, - modifier, - text, - iconType, - size = 'm', - color = 'primary', - ariaLabel, - 'data-test-subj': dataTestSubj, -}) => { - return ( - - {(copy) => ( - { - copy(); - - if (modifier) { - const modifiedCopyValue = modifier(rawValue); - copyToClipboard(modifiedCopyValue); - } else { - copyToClipboard(rawValue); - } - }} - iconType={iconType} - size={size} - color={color} - aria-label={ariaLabel} - data-test-subj={dataTestSubj} - > - {text} - - )} - - ); -}; - -CopyToClipboard.displayName = 'CopyToClipboard'; diff --git a/x-pack/plugins/security_solution/public/flyout/shared/components/expandable_panel.tsx b/x-pack/plugins/security_solution/public/flyout/shared/components/expandable_panel.tsx index 208aa52cfeeca..2f346e70b3676 100644 --- a/x-pack/plugins/security_solution/public/flyout/shared/components/expandable_panel.tsx +++ b/x-pack/plugins/security_solution/public/flyout/shared/components/expandable_panel.tsx @@ -124,6 +124,7 @@ export const ExpandablePanel: React.FC = ({ {expandable && children && toggleIcon} diff --git a/x-pack/plugins/security_solution/public/flyout/shared/components/flyout_navigation.tsx b/x-pack/plugins/security_solution/public/flyout/shared/components/flyout_navigation.tsx index 3629a711b92d0..820b0ac5efcd9 100644 --- a/x-pack/plugins/security_solution/public/flyout/shared/components/flyout_navigation.tsx +++ b/x-pack/plugins/security_solution/public/flyout/shared/components/flyout_navigation.tsx @@ -24,7 +24,7 @@ import { EXPAND_DETAILS_BUTTON_TEST_ID, } from './test_ids'; -export interface PanelNavigationProps { +export interface FlyoutNavigationProps { /** * If true, the expand detail button will be displayed */ @@ -39,7 +39,11 @@ export interface PanelNavigationProps { actions?: React.ReactElement; } -export const FlyoutNavigation: FC = memo( +/** + * Navigation menu on the right panel only, with expand/collapse button and option to + * pass in a list of actions to be displayed on top. + */ +export const FlyoutNavigation: FC = memo( ({ flyoutIsExpandable = false, expandDetails, actions }) => { const { euiTheme } = useEuiTheme(); const { closeLeftPanel, panels } = useExpandableFlyoutContext(); @@ -105,7 +109,7 @@ export const FlyoutNavigation: FC = memo( responsive={false} css={css` padding-left: ${euiTheme.size.s}; - padding-right: ${euiTheme.size.l}; + padding-right: ${euiTheme.size.xl}; height: ${euiTheme.size.xxl}; `} > diff --git a/x-pack/plugins/security_solution/public/flyout/shared/components/flyout_title.stories.tsx b/x-pack/plugins/security_solution/public/flyout/shared/components/flyout_title.stories.tsx new file mode 100644 index 0000000000000..063e9fe9ef38f --- /dev/null +++ b/x-pack/plugins/security_solution/public/flyout/shared/components/flyout_title.stories.tsx @@ -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 React from 'react'; +import type { Story } from '@storybook/react'; +import { EuiLink } from '@elastic/eui'; +import styled from 'styled-components'; +import { FlyoutTitle } from './flyout_title'; + +const FixWidthWrapper = styled.div` + width: 350px; +`; + +const FixWidthLinkWrapper = styled(EuiLink)` + width: 350px; +`; + +export default { + component: FlyoutTitle, + title: 'Flyout/Title', +}; + +export const Default: Story = () => { + return ( + + + + ); +}; + +export const WithoutIcon: Story = () => { + return ( + + + + ); +}; + +export const MultipleLines: Story = () => { + return ( + + + + ); +}; + +export const MoreThanThreeLines: Story = () => { + return ( + + + + ); +}; + +export const TitleInLink: Story = () => { + return ( + + + + ); +}; + +export const MultipleLinesInLink: Story = () => { + return ( + + + + ); +}; + +export const MoreThanThreeLinesInLink: Story = () => { + return ( + + + + ); +}; diff --git a/x-pack/plugins/security_solution/public/flyout/shared/components/flyout_title.test.tsx b/x-pack/plugins/security_solution/public/flyout/shared/components/flyout_title.test.tsx new file mode 100644 index 0000000000000..8668f727201de --- /dev/null +++ b/x-pack/plugins/security_solution/public/flyout/shared/components/flyout_title.test.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 from 'react'; +import { render } from '@testing-library/react'; +import { FlyoutTitle } from './flyout_title'; +import { + FLYOUT_TITLE_TEST_ID, + TITLE_HEADER_ICON_TEST_ID, + TITLE_LINK_ICON_TEST_ID, +} from './test_ids'; + +const title = 'test title'; + +describe('', () => { + it('should render title and icon', () => { + const { getByTestId, queryByTestId } = render( + + ); + + expect(getByTestId(FLYOUT_TITLE_TEST_ID)).toHaveTextContent(title); + expect( + getByTestId(FLYOUT_TITLE_TEST_ID).querySelector('[data-euiicon-type="warning"]') + ).toBeInTheDocument(); + expect(queryByTestId(TITLE_LINK_ICON_TEST_ID)).not.toBeInTheDocument(); + }); + + it('should not render icon if iconType is not passed', () => { + const { getByTestId, queryByTestId } = render(); + + expect(getByTestId(FLYOUT_TITLE_TEST_ID)).toBeInTheDocument(); + expect(queryByTestId(TITLE_HEADER_ICON_TEST_ID)).not.toBeInTheDocument(); + expect(queryByTestId(TITLE_LINK_ICON_TEST_ID)).not.toBeInTheDocument(); + }); + + it('should render popout icon if title is a link', () => { + const { getByTestId } = render(); + + expect(getByTestId(FLYOUT_TITLE_TEST_ID)).toHaveTextContent(title); + expect(getByTestId(TITLE_LINK_ICON_TEST_ID)).toBeInTheDocument(); + expect( + getByTestId(FLYOUT_TITLE_TEST_ID).querySelector('[data-euiicon-type="popout"]') + ).toBeInTheDocument(); + }); + + it('should render title with custom data test subject', () => { + const { getByTestId } = render(); + expect(getByTestId('test-title')).toHaveTextContent(title); + }); +}); diff --git a/x-pack/plugins/security_solution/public/flyout/shared/components/flyout_title.tsx b/x-pack/plugins/security_solution/public/flyout/shared/components/flyout_title.tsx new file mode 100644 index 0000000000000..d9e9d280d38cc --- /dev/null +++ b/x-pack/plugins/security_solution/public/flyout/shared/components/flyout_title.tsx @@ -0,0 +1,121 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type { FC } from 'react'; +import React, { memo, useMemo } from 'react'; +import type { EuiButtonEmptyProps } from '@elastic/eui'; +import { + EuiFlexGroup, + EuiFlexItem, + useEuiTheme, + EuiToolTip, + EuiTitle, + EuiIcon, + EuiTextColor, +} from '@elastic/eui'; +import { css } from '@emotion/react'; +import { + FLYOUT_TITLE_TEST_ID, + TITLE_HEADER_ICON_TEST_ID, + TITLE_LINK_ICON_TEST_ID, +} from './test_ids'; + +export interface FlyoutTitleProps { + /** + * Title text + */ + title: string; + /** + * Optional icon type. If null, no icon is displayed + */ + iconType?: EuiButtonEmptyProps['iconType']; + /** + * Optional boolean to indicate if title is a link. If true, a popout icon is appended + * and the title text is changed to link color + */ + isLink?: boolean; + /** + * Optional data test subject string + */ + 'data-test-subj'?: string; +} + +/** + * Title component with optional icon to indicate the type of document, can be used for text or a link + */ +export const FlyoutTitle: FC = memo( + ({ title, iconType, isLink = false, 'data-test-subj': dataTestSubj = FLYOUT_TITLE_TEST_ID }) => { + const { euiTheme } = useEuiTheme(); + + const titleIcon = useMemo(() => { + return iconType ? ( + + ) : null; + }, [iconType, euiTheme.size.xs]); + + const titleComponent = useMemo(() => { + return ( + + + {title} + + + ); + }, [title, isLink, euiTheme.colors.primaryText]); + + const linkIcon = useMemo(() => { + return ( + + ); + }, [euiTheme.size.xs]); + + return ( + + + +
    + {titleIcon} + {titleComponent} +
    +
    + {isLink && {linkIcon}} +
    +
    + ); + } +); + +FlyoutTitle.displayName = 'FlyoutTitle'; diff --git a/x-pack/plugins/security_solution/public/flyout/shared/components/test_ids.ts b/x-pack/plugins/security_solution/public/flyout/shared/components/test_ids.ts index 737b8afb5fd80..2871cefc93cf8 100644 --- a/x-pack/plugins/security_solution/public/flyout/shared/components/test_ids.ts +++ b/x-pack/plugins/security_solution/public/flyout/shared/components/test_ids.ts @@ -32,3 +32,7 @@ export const EXPAND_DETAILS_BUTTON_TEST_ID = export const COLLAPSE_DETAILS_BUTTON_TEST_ID = `${FLYOUT_NAVIGATION_TEST_ID}CollapseDetailButton` as const; export const HEADER_ACTIONS_TEST_ID = `${FLYOUT_NAVIGATION_TEST_ID}Actions` as const; + +export const FLYOUT_TITLE_TEST_ID = `${PREFIX}Title` as const; +export const TITLE_HEADER_ICON_TEST_ID = `${FLYOUT_TITLE_TEST_ID}Icon` as const; +export const TITLE_LINK_ICON_TEST_ID = `${FLYOUT_TITLE_TEST_ID}LinkIcon` as const; diff --git a/x-pack/plugins/security_solution/public/flyout/shared/utils/copy_to_clipboard.test.tsx b/x-pack/plugins/security_solution/public/flyout/shared/utils/copy_to_clipboard.test.tsx new file mode 100644 index 0000000000000..07816046aa4e1 --- /dev/null +++ b/x-pack/plugins/security_solution/public/flyout/shared/utils/copy_to_clipboard.test.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 { copyFunction } from './copy_to_clipboard'; + +jest.mock('@elastic/eui', () => ({ + ...jest.requireActual('@elastic/eui'), + copyToClipboard: jest.fn(), + EuiCopy: jest.fn(({ children: functionAsChild }) => functionAsChild(jest.fn())), +})); + +describe('copyFunction', () => { + beforeEach(() => { + jest.clearAllMocks(); + }); + + const rawValue = 'rawValue'; + + it('should call copy function', () => { + const euiCopy = jest.fn(); + + copyFunction(euiCopy, rawValue); + + expect(euiCopy).toHaveBeenCalled(); + }); + + it('should call modifier function if passed', () => { + const euiCopy = jest.fn(); + const modifiedFc = jest.fn(); + + copyFunction(euiCopy, rawValue, modifiedFc); + + expect(modifiedFc).toHaveBeenCalledWith(rawValue); + }); +}); diff --git a/x-pack/plugins/security_solution/public/flyout/shared/utils/copy_to_clipboard.tsx b/x-pack/plugins/security_solution/public/flyout/shared/utils/copy_to_clipboard.tsx new file mode 100644 index 0000000000000..efc3523edac34 --- /dev/null +++ b/x-pack/plugins/security_solution/public/flyout/shared/utils/copy_to_clipboard.tsx @@ -0,0 +1,31 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { copyToClipboard } from '@elastic/eui'; + +/** + * Copy to clipboard wrapper component. It allows adding a copy to clipboard functionality to any element. + * It expects the value to be copied with an optional function to modify the value if necessary. + * + * @param copy the copy method from EuiCopy + * @param rawValue the value to save to the clipboard + * @param modifier a function to modify the raw value before saving to the clipboard + */ +export const copyFunction = ( + copy: Function, + rawValue: string, + modifier?: (rawValue: string) => string +) => { + copy(); + + if (modifier) { + const modifiedCopyValue = modifier(rawValue); + copyToClipboard(modifiedCopyValue); + } else { + copyToClipboard(rawValue); + } +}; diff --git a/x-pack/plugins/security_solution/public/management/components/endpoint_responder/command_render_components/get_processes_action.tsx b/x-pack/plugins/security_solution/public/management/components/endpoint_responder/command_render_components/get_processes_action.tsx index fee7a2b73e815..095710e50466a 100644 --- a/x-pack/plugins/security_solution/public/management/components/endpoint_responder/command_render_components/get_processes_action.tsx +++ b/x-pack/plugins/security_solution/public/management/components/endpoint_responder/command_render_components/get_processes_action.tsx @@ -22,16 +22,20 @@ const StyledEuiBasicTable = styled(EuiBasicTable)` table { background-color: transparent; } + .euiTableHeaderCell { border-bottom: ${(props) => props.theme.eui.euiBorderThin}; + .euiTableCellContent__text { font-weight: ${(props) => props.theme.eui.euiFontWeightRegular}; } } + .euiTableRow { &:hover { background-color: ${({ theme: { eui } }) => eui.euiColorEmptyShade} !important; } + .euiTableRowCell { border-top: none !important; border-bottom: none !important; @@ -71,6 +75,7 @@ export const GetProcessesActionResult = memo( () => [ { field: 'user', + 'data-test-subj': 'process_list_user', name: i18n.translate( 'xpack.securitySolution.endpointResponseActions.getProcesses.table.header.user', { defaultMessage: 'USER' } @@ -79,6 +84,7 @@ export const GetProcessesActionResult = memo( }, { field: 'pid', + 'data-test-subj': 'process_list_pid', name: i18n.translate( 'xpack.securitySolution.endpointResponseActions.getProcesses.table.header.pid', { defaultMessage: 'PID' } @@ -87,6 +93,7 @@ export const GetProcessesActionResult = memo( }, { field: 'entity_id', + 'data-test-subj': 'process_list_entity_id', name: i18n.translate( 'xpack.securitySolution.endpointResponseActions.getProcesses.table.header.enityId', { defaultMessage: 'ENTITY ID' } @@ -96,6 +103,7 @@ export const GetProcessesActionResult = memo( { field: 'command', + 'data-test-subj': 'process_list_command', name: i18n.translate( 'xpack.securitySolution.endpointResponseActions.getProcesses.table.header.command', { defaultMessage: 'COMMAND' } @@ -120,7 +128,11 @@ export const GetProcessesActionResult = memo( // Show results return ( - + ); } diff --git a/x-pack/plugins/security_solution/public/management/cypress/e2e/response_actions/response_console/process_operations.cy.ts b/x-pack/plugins/security_solution/public/management/cypress/e2e/response_actions/response_console/process_operations.cy.ts index a50bdf394a9a1..c7120ded692b9 100644 --- a/x-pack/plugins/security_solution/public/management/cypress/e2e/response_actions/response_console/process_operations.cy.ts +++ b/x-pack/plugins/security_solution/public/management/cypress/e2e/response_actions/response_console/process_operations.cy.ts @@ -5,6 +5,7 @@ * 2.0. */ +import { getRunningProcesses } from '../../../tasks/response_actions'; import type { PolicyData } from '../../../../../../common/endpoint/types'; import type { CreateAndEnrollEndpointHostResponse } from '../../../../../../scripts/endpoint/common/endpoint_host_services'; import { @@ -23,16 +24,12 @@ import { enableAllPolicyProtections } from '../../../tasks/endpoint_policy'; import { createEndpointHost } from '../../../tasks/create_endpoint_host'; import { deleteAllLoadedEndpointData } from '../../../tasks/delete_all_endpoint_data'; -// FLAKY: https://github.com/elastic/kibana/issues/170563 -describe.skip('Response console', { tags: ['@ess', '@serverless'] }, () => { +describe('Response console', { tags: ['@ess', '@serverless'] }, () => { beforeEach(() => { login(); }); describe('Processes operations:', () => { - let cronPID: string; - let newCronPID: string; - let indexedPolicy: IndexedFleetEndpointPolicyResponse; let policy: PolicyData; let createdHost: CreateAndEnrollEndpointHostResponse; @@ -70,58 +67,47 @@ describe.skip('Response console', { tags: ['@ess', '@serverless'] }, () => { it('"processes" - should obtain a list of processes', () => { waitForEndpointListPageToBeLoaded(createdHost.hostname); openResponseConsoleFromEndpointList(); + + // get running processes performCommandInputChecks('processes'); submitCommand(); cy.contains('Action pending.').should('exist'); - cy.getByTestSubj('getProcessesSuccessCallout', { timeout: 120000 }).within(() => { + + // on success + cy.getByTestSubj('getProcessListTable', { timeout: 120000 }).within(() => { ['USER', 'PID', 'ENTITY ID', 'COMMAND'].forEach((header) => { cy.contains(header); }); cy.get('tbody > tr').should('have.length.greaterThan', 0); - cy.get('tbody > tr > td').should('contain', '/usr/sbin/cron'); - cy.get('tbody > tr > td') - .contains('/usr/sbin/cron') - .parents('td') - .siblings('td') - .eq(1) - .find('span') - .then((span) => { - cronPID = span.text(); - }); + cy.get('tbody > tr > td').should('contain', '/components/filebeat'); }); }); it('"kill-process --pid" - should kill a process', () => { waitForEndpointListPageToBeLoaded(createdHost.hostname); openResponseConsoleFromEndpointList(); - inputConsoleCommand(`kill-process --pid ${cronPID}`); - submitCommand(); - waitForCommandToBeExecuted('kill-process'); - - performCommandInputChecks('processes'); - submitCommand(); - cy.getByTestSubj('getProcessesSuccessCallout', { timeout: 120000 }).within(() => { - cy.get('tbody > tr > td') - .contains('/usr/sbin/cron') - .parents('td') - .siblings('td') - .eq(1) - .find('span') - .then((span) => { - newCronPID = span.text(); - }); + // get running processes + getRunningProcesses('/components/filebeat').then((pid) => { + // kill the process using PID + inputConsoleCommand(`kill-process --pid ${pid}`); + submitCommand(); + waitForCommandToBeExecuted('kill-process'); }); - expect(newCronPID).to.not.equal(cronPID); }); it('"suspend-process --pid" - should suspend a process', () => { waitForEndpointListPageToBeLoaded(createdHost.hostname); openResponseConsoleFromEndpointList(); - inputConsoleCommand(`suspend-process --pid ${newCronPID}`); - submitCommand(); - waitForCommandToBeExecuted('suspend-process'); + + // get running processes + getRunningProcesses('/components/filebeat').then((pid) => { + // suspend the process using PID + inputConsoleCommand(`suspend-process --pid ${pid}`); + submitCommand(); + waitForCommandToBeExecuted('suspend-process'); + }); }); }); }); diff --git a/x-pack/plugins/security_solution/public/management/cypress/tasks/response_actions.ts b/x-pack/plugins/security_solution/public/management/cypress/tasks/response_actions.ts index 80f1aaba567a0..387f86c0dd160 100644 --- a/x-pack/plugins/security_solution/public/management/cypress/tasks/response_actions.ts +++ b/x-pack/plugins/security_solution/public/management/cypress/tasks/response_actions.ts @@ -5,6 +5,7 @@ * 2.0. */ +import { inputConsoleCommand, submitCommand } from './response_console'; import type { UserAuthzAccessLevel } from '../screens'; import { loadPage, request } from './common'; import { resolvePathVariables } from '../../../common/utils/resolve_path_variables'; @@ -66,6 +67,28 @@ export const visitRuleActions = (ruleId: string) => { cy.getByTestSubj('stepPanelProgress').should('not.exist'); }; +export const getRunningProcesses = (command: string): Cypress.Chainable => { + inputConsoleCommand('processes'); + submitCommand(); + cy.contains('Action pending.').should('exist'); + + // on success + // find pid of process + // traverse back from last column to the second column that has pid + return cy + .getByTestSubj('getProcessListTable', { timeout: 120000 }) + .findByTestSubj('process_list_command') + .contains(command) + .parents('td') + .siblings('td') + .eq(1) + .find('span') + .then((span) => { + // get pid + return Number(span.text()); + }); +}; + export const tryAddingDisabledResponseAction = (itemNumber = 0) => { cy.getByTestSubj('response-actions-wrapper').within(() => { cy.getByTestSubj('Endpoint Security-response-action-type-selection-option').should( diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/view/protection_updates/protection_updates_layout.tsx b/x-pack/plugins/security_solution/public/management/pages/policy/view/protection_updates/protection_updates_layout.tsx index dc260fdb6449d..2ec4ba333e640 100644 --- a/x-pack/plugins/security_solution/public/management/pages/policy/view/protection_updates/protection_updates_layout.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/policy/view/protection_updates/protection_updates_layout.tsx @@ -306,13 +306,22 @@ export const ProtectionUpdatesLayout = React.memo( } )} > - {i18n.translate( - 'xpack.securitySolution.endpoint.protectionUpdates.automaticUpdates.enabled', - { - defaultMessage: - 'Manifest will always be updated to the latest available version. If you want to control updates manually, disable "Update manifest automatically".', - } - )} + + {i18n.translate( + 'xpack.securitySolution.endpoint.protectionUpdates.automaticUpdates.enabled.toggleName', + { + defaultMessage: 'Enable automatic updates', + } + )} + + ), + }} + /> ); } diff --git a/x-pack/plugins/security_solution/public/resolver/view/process_event_dot.tsx b/x-pack/plugins/security_solution/public/resolver/view/process_event_dot.tsx index 4a91e71e3e0b5..13b6513650089 100644 --- a/x-pack/plugins/security_solution/public/resolver/view/process_event_dot.tsx +++ b/x-pack/plugins/security_solution/public/resolver/view/process_event_dot.tsx @@ -291,7 +291,9 @@ const UnstyledProcessEventDot = React.memo( */ false ); - const labelHTMLID = htmlIdGenerator('resolver')(`${nodeID}:label`); + const labelHTMLID = useMemo(() => { + return htmlIdGenerator('resolver')(`${nodeID}:label`); + }, [nodeID]); const isAriaCurrent = nodeID === ariaActiveDescendant; const isAriaSelected = nodeID === selectedNode; @@ -351,6 +353,14 @@ const UnstyledProcessEventDot = React.memo( } }, [processEvent, nodeName]); + const flowToId = useMemo(() => { + return ariaFlowtoNodeID === null ? undefined : nodeHTMLID(ariaFlowtoNodeID); + }, [ariaFlowtoNodeID, nodeHTMLID]); + + const generatedNodeHTMLID = useMemo(() => { + return nodeHTMLID(nodeID); + }, [nodeHTMLID, nodeID]); + /* eslint-disable jsx-a11y/click-events-have-key-events */ return (
    = [ + { product_line: 'security', product_tier: 'complete' }, + { product_line: 'cloud', product_tier: 'complete' }, + { product_line: 'endpoint', product_tier: 'complete' }, +] as const; + const DEFAULT_REGION = 'aws-eu-west-1'; const PROJECT_NAME_PREFIX = 'kibana-cypress-security-solution-ephemeral'; const BASE_ENV_URL = 'https://global.qa.cld.elstc.co'; @@ -82,19 +88,14 @@ const getApiKeyFromElasticCloudJsonFile = (): string | undefined => { async function createSecurityProject( projectName: string, apiKey: string, - ftrConfig: SecuritySolutionDescribeBlockFtrConfig + productTypes: ProductType[] ): Promise { const body: CreateProjectRequestBody = { name: projectName, region_id: DEFAULT_REGION, + product_types: productTypes, }; - const productTypes: ProductType[] = []; - ftrConfig?.productTypes?.forEach((t) => { - productTypes.push(t as ProductType); - }); - if (productTypes.length > 0) body.product_types = productTypes; - try { const response = await axios.post(`${BASE_ENV_URL}/api/v1/serverless/projects/security`, body, { headers: { @@ -325,9 +326,32 @@ function waitForKibanaLogin(kbUrl: string, credentials: Credentials): Promise { + let productTypes: ProductType[] = [...DEFAULT_CONFIGURATION]; + + if (tier) { + productTypes = productTypes.map((product) => ({ + ...product, + product_tier: tier, + })); + } + if (!cloudAddon) { + productTypes = productTypes.filter((product) => product.product_line !== 'cloud'); + } + if (!endpointAddon) { + productTypes = productTypes.filter((product) => product.product_line !== 'endpoint'); + } + + return productTypes; +}; + export const cli = () => { run( - async () => { + async (context) => { log = new ToolingLog({ level: 'info', writeTo: process.stdout, @@ -371,7 +395,22 @@ export const cli = () => { } return acc; }, {} as Record) - ); + ) + .option('tier', { + alias: 't', + type: 'string', + default: 'complete', + }) + .option('endpointAddon', { + alias: 'ea', + type: 'boolean', + default: true, + }) + .option('cloudAddon', { + alias: 'ca', + type: 'boolean', + default: true, + }); log.info(` ---------------------------------------------- @@ -388,6 +427,10 @@ ${JSON.stringify(argv, null, 2)} const cypressConfigFilePath = require.resolve(`../../${argv.configFile}`) as string; const cypressConfigFile = await import(cypressConfigFilePath); + const tier: string = argv.tier; + const endpointAddon: boolean = argv.endpointAddon; + const cloudAddon: boolean = argv.cloudAddon; + log.info(` ---------------------------------------------- Cypress config for file: ${cypressConfigFilePath}: @@ -456,7 +499,10 @@ ${JSON.stringify(cypressConfigFile, null, 2)} await withProcRunner(log, async (procs) => { const id = crypto.randomBytes(8).toString('hex'); const PROJECT_NAME = `${PROJECT_NAME_PREFIX}-${id}`; - const specFileFTRConfig = parseTestFileConfig(filePath); + + const productTypes = isOpen + ? getProductTypes(tier, endpointAddon, cloudAddon) + : (parseTestFileConfig(filePath).productTypes as ProductType[]); if (!API_KEY) { log.info('API KEY to create project could not be retrieved.'); @@ -466,7 +512,7 @@ ${JSON.stringify(cypressConfigFile, null, 2)} log.info(`${id}: Creating project ${PROJECT_NAME}...`); // Creating project for the test to run - const project = await createSecurityProject(PROJECT_NAME, API_KEY, specFileFTRConfig); + const project = await createSecurityProject(PROJECT_NAME, API_KEY, productTypes); if (!project) { log.info('Failed to create project.'); @@ -474,6 +520,11 @@ ${JSON.stringify(cypressConfigFile, null, 2)} return process.exit(1); } + context.addCleanupTask(() => { + const command = `curl -X DELETE ${BASE_ENV_URL}/api/v1/serverless/projects/security/${project.id} -H "Authorization: ApiKey ${API_KEY}"`; + exec(command); + }); + // Reset credentials for elastic user const credentials = await resetCredentials(project.id, id, API_KEY); @@ -553,15 +604,13 @@ ${JSON.stringify(cypressConfigFile, null, 2)} env: cyCustomEnv, }, }); + // Delete serverless project + log.info(`${id} : Deleting project ${PROJECT_NAME}...`); + await deleteSecurityProject(project.id, PROJECT_NAME, API_KEY); } catch (error) { result = error; } } - - // Delete serverless project - log.info(`${id} : Deleting project ${PROJECT_NAME}...`); - await deleteSecurityProject(project.id, PROJECT_NAME, API_KEY); - return result; }); return result; diff --git a/x-pack/plugins/security_solution/server/config.mock.ts b/x-pack/plugins/security_solution/server/config.mock.ts index 36c46300f9f31..855cec11ab16e 100644 --- a/x-pack/plugins/security_solution/server/config.mock.ts +++ b/x-pack/plugins/security_solution/server/config.mock.ts @@ -30,6 +30,7 @@ export const createMockConfig = (): ConfigType => { settings: getDefaultConfigSettings(), experimentalFeatures: parseExperimentalConfigValue(enableExperimental).features, enabled: true, + enableUiSettingsValidations: false, }; }; diff --git a/x-pack/plugins/security_solution/server/config.ts b/x-pack/plugins/security_solution/server/config.ts index 766aca8b5c8be..adc8fbfb1174c 100644 --- a/x-pack/plugins/security_solution/server/config.ts +++ b/x-pack/plugins/security_solution/server/config.ts @@ -114,6 +114,7 @@ export const configSchema = schema.object({ */ prebuiltRulesPackageVersion: schema.maybe(schema.string()), enabled: schema.boolean({ defaultValue: true }), + enableUiSettingsValidations: schema.boolean({ defaultValue: false }), /** * The Max number of Bytes allowed for the `upload` endpoint response action @@ -140,6 +141,7 @@ export type ConfigSchema = TypeOf; export type ConfigType = Omit & { experimentalFeatures: ExperimentalFeatures; settings: ConfigSettings; + enableUiSettingsValidations: boolean; }; export const createConfig = (context: PluginInitializerContext): ConfigType => { diff --git a/x-pack/plugins/security_solution/server/index.ts b/x-pack/plugins/security_solution/server/index.ts index 21eb13b94df04..9c5c1a42749a6 100644 --- a/x-pack/plugins/security_solution/server/index.ts +++ b/x-pack/plugins/security_solution/server/index.ts @@ -6,14 +6,14 @@ */ import type { PluginInitializerContext, PluginConfigDescriptor } from '@kbn/core/server'; -import type { PluginSetup, PluginStart } from './plugin'; -import { Plugin } from './plugin'; +import type { Plugin, PluginSetup, PluginStart } from './plugin'; import type { ConfigSchema, ConfigType } from './config'; import { configSchema } from './config'; import { SIGNALS_INDEX_KEY } from '../common/constants'; import { AppClient } from './types'; -export const plugin = (context: PluginInitializerContext) => { +export const plugin = async (context: PluginInitializerContext) => { + const { Plugin } = await import('./plugin'); return new Plugin(context); }; diff --git a/x-pack/plugins/security_solution/server/plugin.ts b/x-pack/plugins/security_solution/server/plugin.ts index 66f22e0c44bef..c3e20042d224f 100644 --- a/x-pack/plugins/security_solution/server/plugin.ts +++ b/x-pack/plugins/security_solution/server/plugin.ts @@ -170,7 +170,7 @@ export class Plugin implements ISecuritySolutionPlugin { const experimentalFeatures = config.experimentalFeatures; initSavedObjects(core.savedObjects); - initUiSettings(core.uiSettings, experimentalFeatures); + initUiSettings(core.uiSettings, experimentalFeatures, config.enableUiSettingsValidations); appFeaturesService.init(plugins.features); events.forEach((eventConfig) => core.analytics.registerEventType(eventConfig)); diff --git a/x-pack/plugins/security_solution/server/ui_settings.ts b/x-pack/plugins/security_solution/server/ui_settings.ts index 6a41844e9e032..18b5a01b2ad30 100644 --- a/x-pack/plugins/security_solution/server/ui_settings.ts +++ b/x-pack/plugins/security_solution/server/ui_settings.ts @@ -57,7 +57,8 @@ const orderSettings = (settings: SettingsConfig): SettingsConfig => { export const initUiSettings = ( uiSettings: CoreSetup['uiSettings'], - experimentalFeatures: ExperimentalFeatures + experimentalFeatures: ExperimentalFeatures, + validationsEnabled: boolean ) => { const securityUiSettings: Record> = { [DEFAULT_APP_REFRESH_INTERVAL]: { @@ -115,7 +116,9 @@ export const initUiSettings = ( }), category: [APP_ID], requiresPageReload: true, - schema: schema.arrayOf(schema.string()), + schema: validationsEnabled + ? schema.arrayOf(schema.string(), { maxSize: 50 }) + : schema.arrayOf(schema.string()), }, [DEFAULT_THREAT_INDEX_KEY]: { name: i18n.translate('xpack.securitySolution.uiSettings.defaultThreatIndexLabel', { @@ -132,7 +135,9 @@ export const initUiSettings = ( ), category: [APP_ID], requiresPageReload: true, - schema: schema.arrayOf(schema.string()), + schema: validationsEnabled + ? schema.arrayOf(schema.string(), { maxSize: 10 }) + : schema.arrayOf(schema.string()), }, [DEFAULT_ANOMALY_SCORE]: { name: i18n.translate('xpack.securitySolution.uiSettings.defaultAnomalyScoreLabel', { @@ -149,7 +154,7 @@ export const initUiSettings = ( ), category: [APP_ID], requiresPageReload: true, - schema: schema.number(), + schema: validationsEnabled ? schema.number({ max: 100, min: 0 }) : schema.number(), }, [ENABLE_NEWS_FEED_SETTING]: { name: i18n.translate('xpack.securitySolution.uiSettings.enableNewsFeedLabel', { diff --git a/x-pack/plugins/security_solution_ess/server/index.ts b/x-pack/plugins/security_solution_ess/server/index.ts index ebb28fda2cf0a..ad6f30ea6d771 100644 --- a/x-pack/plugins/security_solution_ess/server/index.ts +++ b/x-pack/plugins/security_solution_ess/server/index.ts @@ -7,12 +7,12 @@ import type { PluginInitializerContext } from '@kbn/core/server'; -import { SecuritySolutionEssPlugin } from './plugin'; export { config } from './config'; // This exports static code and TypeScript types, // as well as, Kibana Platform `plugin()` initializer. -export function plugin(_initializerContext: PluginInitializerContext) { +export async function plugin(_initializerContext: PluginInitializerContext) { + const { SecuritySolutionEssPlugin } = await import('./plugin'); return new SecuritySolutionEssPlugin(); } diff --git a/x-pack/plugins/security_solution_serverless/server/index.ts b/x-pack/plugins/security_solution_serverless/server/index.ts index 44ac7142240b9..a0e2cba23fd62 100644 --- a/x-pack/plugins/security_solution_serverless/server/index.ts +++ b/x-pack/plugins/security_solution_serverless/server/index.ts @@ -7,13 +7,13 @@ import type { PluginInitializerContext } from '@kbn/core/server'; -import { SecuritySolutionServerlessPlugin } from './plugin'; export { config } from './config'; // This exports static code and TypeScript types, // as well as, Kibana Platform `plugin()` initializer. -export function plugin(initializerContext: PluginInitializerContext) { +export async function plugin(initializerContext: PluginInitializerContext) { + const { SecuritySolutionServerlessPlugin } = await import('./plugin'); return new SecuritySolutionServerlessPlugin(initializerContext); } diff --git a/x-pack/plugins/serverless/server/index.ts b/x-pack/plugins/serverless/server/index.ts index 04f08ac6ed4cc..350b7a6c27641 100644 --- a/x-pack/plugins/serverless/server/index.ts +++ b/x-pack/plugins/serverless/server/index.ts @@ -6,10 +6,10 @@ */ import { PluginInitializerContext } from '@kbn/core/server'; -import { ServerlessPlugin } from './plugin'; export { config } from './config'; -export const plugin = (initializerContext: PluginInitializerContext) => { +export const plugin = async (initializerContext: PluginInitializerContext) => { + const { ServerlessPlugin } = await import('./plugin'); return new ServerlessPlugin(initializerContext); }; diff --git a/x-pack/plugins/serverless_observability/server/index.ts b/x-pack/plugins/serverless_observability/server/index.ts index c45e363a429bf..f0dbaa87b5c98 100644 --- a/x-pack/plugins/serverless_observability/server/index.ts +++ b/x-pack/plugins/serverless_observability/server/index.ts @@ -7,13 +7,13 @@ import { PluginInitializerContext } from '@kbn/core/server'; -import { ServerlessObservabilityPlugin } from './plugin'; export { config } from './config'; // This exports static code and TypeScript types, // as well as, Kibana Platform `plugin()` initializer. -export function plugin(initializerContext: PluginInitializerContext) { +export async function plugin(initializerContext: PluginInitializerContext) { + const { ServerlessObservabilityPlugin } = await import('./plugin'); return new ServerlessObservabilityPlugin(initializerContext); } diff --git a/x-pack/plugins/serverless_search/kibana.jsonc b/x-pack/plugins/serverless_search/kibana.jsonc index 0ac92bc197468..a9000e7542475 100644 --- a/x-pack/plugins/serverless_search/kibana.jsonc +++ b/x-pack/plugins/serverless_search/kibana.jsonc @@ -15,6 +15,7 @@ "requiredPlugins": [ "cloud", "console", + "dataViews", "dashboard", "devTools", "discover", diff --git a/x-pack/plugins/serverless_search/public/index.ts b/x-pack/plugins/serverless_search/public/index.ts index 5031ccc61d1ac..a0f2c3c6eceb9 100644 --- a/x-pack/plugins/serverless_search/public/index.ts +++ b/x-pack/plugins/serverless_search/public/index.ts @@ -4,7 +4,6 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ - import { ServerlessSearchPlugin } from './plugin'; // This exports static code and TypeScript types, diff --git a/x-pack/plugins/serverless_search/server/plugin.ts b/x-pack/plugins/serverless_search/server/plugin.ts index 2651d6a2f38da..98f60c803972b 100644 --- a/x-pack/plugins/serverless_search/server/plugin.ts +++ b/x-pack/plugins/serverless_search/server/plugin.ts @@ -11,9 +11,11 @@ import type { PluginInitializerContext, Plugin, CoreSetup, + CoreStart, } from '@kbn/core/server'; import type { SecurityPluginStart } from '@kbn/security-plugin/server'; import { SEARCH_PROJECT_SETTINGS } from '@kbn/serverless-search-settings'; +import { DataViewsServerPluginStart } from '@kbn/data-views-plugin/server'; import { registerApiKeyRoutes } from './routes/api_key_routes'; import { registerIndicesRoutes } from './routes/indices_routes'; @@ -51,6 +53,27 @@ export class ServerlessSearchPlugin this.config = initializerContext.config.get(); this.logger = initializerContext.logger.get(); } + private async createDefaultDataView(core: CoreStart, dataViews: DataViewsServerPluginStart) { + const dataViewsService = await dataViews.dataViewsServiceFactory( + core.savedObjects.createInternalRepository(), + core.elasticsearch.client.asInternalUser, + undefined, + true + ); + const dataViewExists = await dataViewsService.get('default_all_data_id').catch(() => false); + if (!dataViewExists) { + const defaultDataViewExists = await dataViewsService.defaultDataViewExists(); + if (!defaultDataViewExists) { + await dataViewsService.createAndSave({ + allowNoIndex: false, + name: 'default:all-data', + title: '*', + id: 'default_all_data_id', + }); + } + } + return; + } public setup( { getStartServices, http }: CoreSetup, @@ -75,7 +98,8 @@ export class ServerlessSearchPlugin return {}; } - public start() { + public start(core: CoreStart, { dataViews }: StartDependencies) { + this.createDefaultDataView(core, dataViews); return {}; } diff --git a/x-pack/plugins/serverless_search/server/types.ts b/x-pack/plugins/serverless_search/server/types.ts index c2eee3d0078a7..3cbd26ad2dd5f 100644 --- a/x-pack/plugins/serverless_search/server/types.ts +++ b/x-pack/plugins/serverless_search/server/types.ts @@ -5,6 +5,7 @@ * 2.0. */ +import { DataViewsServerPluginStart } from '@kbn/data-views-plugin/server'; import type { SecurityPluginStart } from '@kbn/security-plugin/server'; import type { ServerlessPluginSetup } from '@kbn/serverless/server'; @@ -14,6 +15,7 @@ export interface ServerlessSearchPluginSetup {} export interface ServerlessSearchPluginStart {} export interface StartDependencies { + dataViews: DataViewsServerPluginStart; security: SecurityPluginStart; } export interface SetupDependencies { diff --git a/x-pack/plugins/serverless_search/tsconfig.json b/x-pack/plugins/serverless_search/tsconfig.json index c07cff77aa19e..f58828f69569b 100644 --- a/x-pack/plugins/serverless_search/tsconfig.json +++ b/x-pack/plugins/serverless_search/tsconfig.json @@ -35,6 +35,7 @@ "@kbn/react-kibana-context-theme", "@kbn/search-connectors", "@kbn/shared-ux-router", + "@kbn/data-views-plugin", "@kbn/kibana-utils-plugin", "@kbn/index-management-plugin", ] diff --git a/x-pack/plugins/session_view/public/components/session_view/index.tsx b/x-pack/plugins/session_view/public/components/session_view/index.tsx index 18accecb36dd5..4eaa905f9852d 100644 --- a/x-pack/plugins/session_view/public/components/session_view/index.tsx +++ b/x-pack/plugins/session_view/public/components/session_view/index.tsx @@ -4,6 +4,7 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ +import { v4 as uuidv4 } from 'uuid'; import React, { useState, useCallback, useEffect, useMemo, useRef } from 'react'; import { EuiEmptyPrompt, @@ -98,6 +99,7 @@ export const SessionView = ({ const [currentJumpToCursor, setCurrentJumpToCursor] = useState(jumpToCursor); const [currentJumpToEntityId, setCurrentJumpToEntityId] = useState(jumpToEntityId); const [currentJumpToOutputEntityId, setCurrentJumpToOutputEntityId] = useState(''); + const sessionViewId = useMemo(() => `session-view-uuid-${uuidv4()}`, []); const styles = useStyles({ height, isFullScreen }); @@ -399,7 +401,7 @@ export const SessionView = ({ {(EuiResizablePanel, EuiResizableButton, { togglePanel }) => { detailPanelCollapseFn.current = () => { - togglePanel?.('session-detail-panel', { direction: 'left' }); + togglePanel?.(sessionViewId, { direction: 'left' }); }; return ( @@ -458,7 +460,7 @@ export const SessionView = ({ new SnapshotRestoreServerPlugin(ctx); +export const plugin = async (ctx: PluginInitializerContext) => { + const { SnapshotRestoreServerPlugin } = await import('./plugin'); + return new SnapshotRestoreServerPlugin(ctx); +}; diff --git a/x-pack/plugins/spaces/server/index.ts b/x-pack/plugins/spaces/server/index.ts index b7b97692f803e..ba949628c56e1 100644 --- a/x-pack/plugins/spaces/server/index.ts +++ b/x-pack/plugins/spaces/server/index.ts @@ -8,7 +8,6 @@ import type { PluginConfigDescriptor, PluginInitializerContext } from '@kbn/core/server'; import { ConfigSchema } from './config'; -import { SpacesPlugin } from './plugin'; // These exports are part of public Spaces plugin contract, any change in signature of exported // functions or removal of exports should be considered as a breaking change. Ideally we should @@ -37,5 +36,7 @@ export const config: PluginConfigDescriptor = { }, }; -export const plugin = (initializerContext: PluginInitializerContext) => - new SpacesPlugin(initializerContext); +export const plugin = async (initializerContext: PluginInitializerContext) => { + const { SpacesPlugin } = await import('./plugin'); + return new SpacesPlugin(initializerContext); +}; diff --git a/x-pack/plugins/stack_alerts/server/index.ts b/x-pack/plugins/stack_alerts/server/index.ts index d6ca5109007d7..92fcf8730ec78 100644 --- a/x-pack/plugins/stack_alerts/server/index.ts +++ b/x-pack/plugins/stack_alerts/server/index.ts @@ -7,7 +7,6 @@ import { get } from 'lodash'; import { schema, TypeOf } from '@kbn/config-schema'; import { PluginConfigDescriptor, PluginInitializerContext } from '@kbn/core/server'; -import { AlertingBuiltinsPlugin } from './plugin'; export { ID as INDEX_THRESHOLD_ID } from './rule_types/index_threshold/rule_type'; export const configSchema = schema.object({}); @@ -34,4 +33,7 @@ export const config: PluginConfigDescriptor = { ], }; -export const plugin = (ctx: PluginInitializerContext) => new AlertingBuiltinsPlugin(ctx); +export const plugin = async (ctx: PluginInitializerContext) => { + const { AlertingBuiltinsPlugin } = await import('./plugin'); + return new AlertingBuiltinsPlugin(ctx); +}; diff --git a/x-pack/plugins/stack_connectors/common/experimental_features.ts b/x-pack/plugins/stack_connectors/common/experimental_features.ts index 4ac02dd9f06db..b7f1fe2c1b87b 100644 --- a/x-pack/plugins/stack_connectors/common/experimental_features.ts +++ b/x-pack/plugins/stack_connectors/common/experimental_features.ts @@ -12,7 +12,7 @@ export type ExperimentalFeatures = typeof allowedExperimentalValues; * This object is then used to validate and parse the value entered. */ export const allowedExperimentalValues = Object.freeze({ - isMustacheAutocompleteOn: false, + isMustacheAutocompleteOn: true, sentinelOneConnectorOn: false, }); diff --git a/x-pack/plugins/stack_connectors/public/connector_types/email/email_params.tsx b/x-pack/plugins/stack_connectors/public/connector_types/email/email_params.tsx index 2100e2b0d823c..7da7ae0ce417d 100644 --- a/x-pack/plugins/stack_connectors/public/connector_types/email/email_params.tsx +++ b/x-pack/plugins/stack_connectors/public/connector_types/email/email_params.tsx @@ -5,7 +5,7 @@ * 2.0. */ -import React, { useState, useEffect, useMemo } from 'react'; +import React, { useState, useEffect } from 'react'; import { FormattedMessage } from '@kbn/i18n-react'; import { EuiComboBox, EuiButtonEmpty, EuiFormRow } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; @@ -15,8 +15,6 @@ import { TextAreaWithMessageVariables, } from '@kbn/triggers-actions-ui-plugin/public'; import { EmailActionParams } from '../types'; -import { getIsExperimentalFeatureEnabled } from '../../common/get_experimental_features'; -import { TextAreaWithAutocomplete } from '../../components/text_area_with_autocomplete'; const noop = () => {}; @@ -32,8 +30,8 @@ export const EmailParamsFields = ({ onBlur = noop, showEmailSubjectAndMessage = true, useDefaultMessage, + ruleTypeId, }: ActionParamsProps) => { - const isMustacheAutocompleteOn = getIsExperimentalFeatureEnabled('isMustacheAutocompleteOn'); const { to, cc, bcc, subject, message } = actionParams; const toOptions = to ? to.map((label: string) => ({ label })) : []; const ccOptions = cc ? cc.map((label: string) => ({ label })) : []; @@ -64,10 +62,6 @@ export const EmailParamsFields = ({ const isBCCInvalid: boolean = errors.bcc !== undefined && errors.bcc.length > 0 && bcc !== undefined; - const TextAreaComponent = useMemo(() => { - return isMustacheAutocompleteOn ? TextAreaWithAutocomplete : TextAreaWithMessageVariables; - }, [isMustacheAutocompleteOn]); - return ( <> )} {showEmailSubjectAndMessage && ( - { diff --git a/x-pack/plugins/stack_connectors/public/connector_types/server_log/server_log_params.tsx b/x-pack/plugins/stack_connectors/public/connector_types/server_log/server_log_params.tsx index 7c74245289833..95314c5fb7126 100644 --- a/x-pack/plugins/stack_connectors/public/connector_types/server_log/server_log_params.tsx +++ b/x-pack/plugins/stack_connectors/public/connector_types/server_log/server_log_params.tsx @@ -37,7 +37,7 @@ export const ServerLogParamsFields: React.FunctionComponent< editAction('level', 'info', index); } // eslint-disable-next-line react-hooks/exhaustive-deps - }, []); + }, [actionParams.level]); const [[isUsingDefault, defaultMessageUsed], setDefaultMessageUsage] = useState< [boolean, string | undefined] diff --git a/x-pack/plugins/stack_connectors/public/connector_types/slack/action_form.test.tsx b/x-pack/plugins/stack_connectors/public/connector_types/slack/action_form.test.tsx index 4e86a25ed26d8..ed36daef3abf4 100644 --- a/x-pack/plugins/stack_connectors/public/connector_types/slack/action_form.test.tsx +++ b/x-pack/plugins/stack_connectors/public/connector_types/slack/action_form.test.tsx @@ -16,6 +16,7 @@ import { IToasts } from '@kbn/core/public'; import { __IntlProvider as IntlProvider } from '@kbn/i18n-react'; import { getConnectorType as getSlackConnectorType } from './slack'; import { getSlackApiConnectorType } from '../slack_api'; +import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; jest.mock('@kbn/triggers-actions-ui-plugin/public/common/lib/kibana'); jest.mock('@kbn/kibana-react-plugin/public/ui_settings/use_ui_setting', () => ({ @@ -51,6 +52,14 @@ const { loadActionTypes } = jest.requireMock( '@kbn/triggers-actions-ui-plugin/public/application/lib/action_connector_api/connector_types' ); const useKibanaMock = useKibana as jest.Mocked; +const queryClient = new QueryClient({ + defaultOptions: { + queries: { + retry: false, + cacheTime: 0, + }, + }, +}); // GET api/actions/connector_types?feature_id=alerting loadActionTypes.mockResolvedValue([ @@ -95,6 +104,7 @@ actionTypeRegistry.register(getSlackApiConnectorType()); const baseProps = { actions: [], defaultActionGroupId: 'metrics.inventory_threshold.fired', + ruleTypeId: 'metrics.inventory_threshold', hasAlertsMappings: true, featureId: 'alerting', recoveryActionGroup: 'recovered', @@ -170,7 +180,9 @@ describe('ActionForm - Slack API Connector', () => { render( - + + + ); diff --git a/x-pack/plugins/stack_connectors/server/connector_types/openai/openai.test.ts b/x-pack/plugins/stack_connectors/server/connector_types/openai/openai.test.ts index 7539f3b0d389f..7769dd8592faf 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/openai/openai.test.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/openai/openai.test.ts @@ -274,13 +274,22 @@ describe('OpenAIConnector', () => { }); describe('invokeStream', () => { - let stream; + const mockStream = ( + dataToStream: string[] = [ + 'data: {"object":"chat.completion.chunk","choices":[{"delta":{"content":"My"}}]}\ndata: {"object":"chat.completion.chunk","choices":[{"delta":{"content":" new"}}]}', + ] + ) => { + const streamMock = createStreamMock(); + dataToStream.forEach((chunk) => { + streamMock.write(chunk); + }); + streamMock.complete(); + mockRequest = jest.fn().mockResolvedValue({ ...mockResponse, data: streamMock.transform }); + return mockRequest; + }; beforeEach(() => { - stream = createStreamMock(); - stream.write(`data: ${JSON.stringify(mockResponse.data)}`); - mockRequest = jest.fn().mockResolvedValue({ ...mockResponse, data: stream.transform }); // @ts-ignore - connector.request = mockRequest; + connector.request = mockStream(); }); it('the API call is successful with correct request parameters', async () => { @@ -307,6 +316,43 @@ describe('OpenAIConnector', () => { }); it('transforms the response into a string', async () => { + // @ts-ignore + connector.request = mockStream(); + const response = await connector.invokeStream(sampleOpenAiBody); + + let responseBody: string = ''; + response.on('data', (data: string) => { + responseBody += data.toString(); + }); + await waitFor(() => { + expect(responseBody).toEqual('My new'); + }); + }); + it('correctly buffers stream of json lines', async () => { + const chunk1 = `data: {"object":"chat.completion.chunk","choices":[{"delta":{"content":"My"}}]}\ndata: {"object":"chat.completion.chunk","choices":[{"delta":{"content":" new"}}]}`; + const chunk2 = `\ndata: {"object":"chat.completion.chunk","choices":[{"delta":{"content":" message"}}]}\ndata: [DONE]`; + + // @ts-ignore + connector.request = mockStream([chunk1, chunk2]); + + const response = await connector.invokeStream(sampleOpenAiBody); + + let responseBody: string = ''; + response.on('data', (data: string) => { + responseBody += data.toString(); + }); + await waitFor(() => { + expect(responseBody).toEqual('My new message'); + }); + }); + it('correctly buffers partial lines', async () => { + const chunk1 = `data: {"object":"chat.completion.chunk","choices":[{"delta":{"content":"My"}}]}\ndata: {"object":"chat.completion.chunk","choices":[{"delta":{"content":" new"`; + + const chunk2 = `}}]}\ndata: {"object":"chat.completion.chunk","choices":[{"delta":{"content":" message"}}]}\ndata: [DONE]`; + + // @ts-ignore + connector.request = mockStream([chunk1, chunk2]); + const response = await connector.invokeStream(sampleOpenAiBody); let responseBody: string = ''; @@ -314,7 +360,7 @@ describe('OpenAIConnector', () => { responseBody += data.toString(); }); await waitFor(() => { - expect(responseBody).toEqual(mockResponseString); + expect(responseBody).toEqual('My new message'); }); }); }); @@ -655,7 +701,7 @@ function createStreamMock() { return { write: (data: string) => { - transform.push(`${data}\n`); + transform.push(data); }, fail: () => { transform.emit('error', new Error('Stream failed')); diff --git a/x-pack/plugins/stack_connectors/server/connector_types/openai/openai.ts b/x-pack/plugins/stack_connectors/server/connector_types/openai/openai.ts index 02ad7bcdec6a9..78fca4bd84198 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/openai/openai.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/openai/openai.ts @@ -203,6 +203,7 @@ export class OpenAIConnector extends SubActionConnector { body: JSON.stringify(body), stream: true, })) as unknown as IncomingMessage; + return res.pipe(new PassThrough()).pipe(transformToString()); } @@ -234,24 +235,38 @@ export class OpenAIConnector extends SubActionConnector { * parses the proprietary OpenAI response into a string of the response text alone, * returning the response string to the stream */ -const transformToString = () => - new Transform({ +const transformToString = () => { + let lineBuffer: string = ''; + const decoder = new TextDecoder(); + + return new Transform({ transform(chunk, encoding, callback) { - const decoder = new TextDecoder(); - const encoder = new TextEncoder(); - const nextChunk = decoder - .decode(chunk) - .split('\n') - // every line starts with "data: ", we remove it and are left with stringified JSON or the string "[DONE]" - .map((str) => str.substring(6)) - // filter out empty lines and the "[DONE]" string - .filter((str) => !!str && str !== '[DONE]') - .map((line) => { - const openaiResponse = JSON.parse(line); - return openaiResponse.choices[0]?.delta.content ?? ''; - }) - .join(''); - const newChunk = encoder.encode(nextChunk); - callback(null, newChunk); + const chunks = decoder.decode(chunk); + const lines = chunks.split('\n'); + lines[0] = lineBuffer + lines[0]; + lineBuffer = lines.pop() || ''; + callback(null, getNextChunk(lines)); + }, + flush(callback) { + // Emit an additional chunk with the content of lineBuffer if it has length + if (lineBuffer.length > 0) { + callback(null, getNextChunk([lineBuffer])); + } else { + callback(); + } }, }); +}; + +const getNextChunk = (lines: string[]) => { + const encoder = new TextEncoder(); + const nextChunk = lines + .map((str) => str.substring(6)) + .filter((str) => !!str && str !== '[DONE]') + .map((line) => { + const openaiResponse = JSON.parse(line); + return openaiResponse.choices[0]?.delta.content ?? ''; + }) + .join(''); + return encoder.encode(nextChunk); +}; diff --git a/x-pack/plugins/stack_connectors/server/index.ts b/x-pack/plugins/stack_connectors/server/index.ts index c41b13ee2b15c..4b8ae8580cf96 100644 --- a/x-pack/plugins/stack_connectors/server/index.ts +++ b/x-pack/plugins/stack_connectors/server/index.ts @@ -5,7 +5,6 @@ * 2.0. */ import { PluginConfigDescriptor, PluginInitializerContext } from '@kbn/core/server'; -import { StackConnectorsPlugin } from './plugin'; import { configSchema, ConfigSchema } from './config'; export const config: PluginConfigDescriptor = { @@ -15,5 +14,7 @@ export const config: PluginConfigDescriptor = { schema: configSchema, }; -export const plugin = (initContext: PluginInitializerContext) => - new StackConnectorsPlugin(initContext); +export const plugin = async (initContext: PluginInitializerContext) => { + const { StackConnectorsPlugin } = await import('./plugin'); + return new StackConnectorsPlugin(initContext); +}; diff --git a/x-pack/plugins/stack_connectors/tsconfig.json b/x-pack/plugins/stack_connectors/tsconfig.json index 4e47b703bf433..e577ce018bdf3 100644 --- a/x-pack/plugins/stack_connectors/tsconfig.json +++ b/x-pack/plugins/stack_connectors/tsconfig.json @@ -8,7 +8,7 @@ // have to declare *.json explicitly due to https://github.com/microsoft/TypeScript/issues/25636 "server/**/*.json", "common/**/*", - "public/**/*" + "public/**/*", ], "kbn_references": [ "@kbn/core", @@ -33,7 +33,6 @@ "@kbn/core-saved-objects-common", "@kbn/core-http-browser-mocks", "@kbn/core-saved-objects-api-server-mocks", - "@kbn/alerts-ui-shared", "@kbn/alerting-plugin", "@kbn/securitysolution-ecs", "@kbn/ui-theme", diff --git a/x-pack/plugins/synthetics/server/index.ts b/x-pack/plugins/synthetics/server/index.ts index 3ed326d1fc143..80cbe388a3015 100644 --- a/x-pack/plugins/synthetics/server/index.ts +++ b/x-pack/plugins/synthetics/server/index.ts @@ -6,9 +6,9 @@ */ import { PluginInitializerContext } from '@kbn/core/server'; -import { Plugin } from './plugin'; - -export const plugin = (initializerContext: PluginInitializerContext) => - new Plugin(initializerContext); +export const plugin = async (initializerContext: PluginInitializerContext) => { + const { Plugin } = await import('./plugin'); + return new Plugin(initializerContext); +}; export { config } from '../common/config'; diff --git a/x-pack/plugins/synthetics/server/routes/monitor_cruds/monitor_validation.ts b/x-pack/plugins/synthetics/server/routes/monitor_cruds/monitor_validation.ts index 4fbaed7417315..8b983c0c8f93c 100644 --- a/x-pack/plugins/synthetics/server/routes/monitor_cruds/monitor_validation.ts +++ b/x-pack/plugins/synthetics/server/routes/monitor_cruds/monitor_validation.ts @@ -18,23 +18,23 @@ import { DataStream, DataStreamCodec, HTTPFieldsCodec, - ICMPSimpleFieldsCodec, MonitorFields, TCPFieldsCodec, SyntheticsMonitor, Locations, + ICMPFieldsCodec, } from '../../../common/runtime_types'; import { ALLOWED_SCHEDULES_IN_MINUTES } from '../../../common/constants/monitor_defaults'; type MonitorCodecType = - | typeof ICMPSimpleFieldsCodec + | typeof ICMPFieldsCodec | typeof TCPFieldsCodec | typeof HTTPFieldsCodec | typeof BrowserFieldsCodec; const monitorTypeToCodecMap: Record = { - [DataStream.ICMP]: ICMPSimpleFieldsCodec, + [DataStream.ICMP]: ICMPFieldsCodec, [DataStream.TCP]: TCPFieldsCodec, [DataStream.HTTP]: HTTPFieldsCodec, [DataStream.BROWSER]: BrowserFieldsCodec, @@ -67,7 +67,7 @@ export function validateMonitor(monitorFields: MonitorFields): ValidationResult } // Cast it to ICMPCodec to satisfy typing. During runtime, correct codec will be used to decode. - const SyntheticsMonitorCodec = monitorTypeToCodecMap[monitorType] as typeof ICMPSimpleFieldsCodec; + const SyntheticsMonitorCodec = monitorTypeToCodecMap[monitorType] as typeof ICMPFieldsCodec; if (!SyntheticsMonitorCodec) { return { diff --git a/x-pack/plugins/task_manager/server/index.ts b/x-pack/plugins/task_manager/server/index.ts index a6e9943df2d3c..a7555b3316a8e 100644 --- a/x-pack/plugins/task_manager/server/index.ts +++ b/x-pack/plugins/task_manager/server/index.ts @@ -7,10 +7,12 @@ import { get } from 'lodash'; import { PluginConfigDescriptor, PluginInitializerContext } from '@kbn/core/server'; -import { TaskManagerPlugin } from './plugin'; import { configSchema, TaskManagerConfig, MAX_WORKERS_LIMIT } from './config'; -export const plugin = (initContext: PluginInitializerContext) => new TaskManagerPlugin(initContext); +export const plugin = async (initContext: PluginInitializerContext) => { + const { TaskManagerPlugin } = await import('./plugin'); + return new TaskManagerPlugin(initContext); +}; export type { TaskInstance, @@ -34,7 +36,12 @@ export { isEphemeralTaskRejectedDueToCapacityError, isSkipError, createSkipError, + createTaskRunError, + TaskErrorSource, } from './task_running'; + +export type { DecoratedError } from './task_running'; + export type { RunNowResult, BulkUpdateTaskResult } from './task_scheduling'; export { getOldestIdleActionTask } from './queries/oldest_idle_action_task'; export { diff --git a/x-pack/plugins/task_manager/server/polling/task_poller.ts b/x-pack/plugins/task_manager/server/polling/task_poller.ts index 5c046b0c68a3d..812f29d170e96 100644 --- a/x-pack/plugins/task_manager/server/polling/task_poller.ts +++ b/x-pack/plugins/task_manager/server/polling/task_poller.ts @@ -13,6 +13,7 @@ import { Observable, Subject } from 'rxjs'; import { Option, none } from 'fp-ts/lib/Option'; import { Logger } from '@kbn/core/server'; +import { TaskErrorSource } from '../task_running'; import { Result, asOk, asErr } from '../lib/result_type'; type WorkFn = () => Promise; @@ -128,10 +129,12 @@ function asPollingError(err: string | Error, type: PollingErrorType, data: Op export class PollingError extends Error { public readonly type: PollingErrorType; public readonly data: Option; + public readonly source: TaskErrorSource; constructor(message: string, type: PollingErrorType, data: Option) { super(message); Object.setPrototypeOf(this, new.target.prototype); this.type = type; this.data = data; + this.source = TaskErrorSource.FRAMEWORK; } } diff --git a/x-pack/plugins/task_manager/server/task.ts b/x-pack/plugins/task_manager/server/task.ts index b4c7d38e4ec3a..b00f06b6a2395 100644 --- a/x-pack/plugins/task_manager/server/task.ts +++ b/x-pack/plugins/task_manager/server/task.ts @@ -8,6 +8,7 @@ import { ObjectType, schema, TypeOf } from '@kbn/config-schema'; import { isErr, tryAsResult } from './lib/result_type'; import { Interval, isInterval, parseIntervalAsMillisecond } from './lib/intervals'; +import { DecoratedError } from './task_running'; /* * Type definitions and validations for tasks. @@ -47,7 +48,7 @@ export type SuccessfulRunResult = { * recurring task). See the RunContext type definition for more details. */ state: Record; - hasError?: boolean; + taskRunError?: DecoratedError; } & ( | // ensure a SuccessfulRunResult can either specify a new `runAt` or a new `schedule`, but not both { @@ -75,7 +76,7 @@ export type FailedRunResult = SuccessfulRunResult & { * If specified, indicates that the task failed to accomplish its work. This is * logged out as a warning, and the task will be reattempted after a delay. */ - error: Error; + error: DecoratedError; }; export type RunResult = FailedRunResult | SuccessfulRunResult; diff --git a/x-pack/plugins/task_manager/server/task_events.ts b/x-pack/plugins/task_manager/server/task_events.ts index 277eddee6e435..c0ae11528f843 100644 --- a/x-pack/plugins/task_manager/server/task_events.ts +++ b/x-pack/plugins/task_manager/server/task_events.ts @@ -12,7 +12,7 @@ import { ConcreteTaskInstance } from './task'; import { Result, Err } from './lib/result_type'; import { ClaimAndFillPoolResult } from './lib/fill_pool'; import { PollingError } from './polling'; -import { TaskRunResult } from './task_running'; +import { DecoratedError, TaskRunResult } from './task_running'; import { EphemeralTaskInstanceRequest } from './ephemeral_task_lifecycle'; import type { EventLoopDelayConfig } from './config'; import { TaskManagerMetrics } from './metrics/task_metrics_collector'; @@ -75,7 +75,7 @@ export interface RanTask { isExpired: boolean; } export type ErroredTask = RanTask & { - error: Error; + error: DecoratedError; }; export type TaskMarkRunning = TaskEvent; diff --git a/x-pack/plugins/task_manager/server/task_running/errors.ts b/x-pack/plugins/task_manager/server/task_running/errors.ts index 690615c442235..2d8e09b5c24e0 100644 --- a/x-pack/plugins/task_manager/server/task_running/errors.ts +++ b/x-pack/plugins/task_manager/server/task_running/errors.ts @@ -13,10 +13,17 @@ const CODE_SKIP = 'TaskManager/skip'; const code = Symbol('TaskManagerErrorCode'); const retry = Symbol('TaskManagerErrorRetry'); +const source = Symbol('TaskManagerErrorSource'); + +export enum TaskErrorSource { + FRAMEWORK = 'framework', + USER = 'user', +} export interface DecoratedError extends Error { [code]?: string; [retry]?: Date | boolean; + [source]?: TaskErrorSource; } export class EphemeralTaskRejectedDueToCapacityError extends Error { @@ -40,8 +47,9 @@ export function isUnrecoverableError(error: Error | DecoratedError) { return isTaskManagerError(error) && error[code] === CODE_UNRECOVERABLE; } -export function throwUnrecoverableError(error: Error) { +export function throwUnrecoverableError(error: Error, errorSource = TaskErrorSource.FRAMEWORK) { (error as DecoratedError)[code] = CODE_UNRECOVERABLE; + (error as DecoratedError)[source] = errorSource; throw error; } @@ -52,14 +60,10 @@ export function isRetryableError(error: Error | DecoratedError) { return null; } -export function createRetryableError(error: Error, shouldRetry: Date | boolean): DecoratedError { +export function throwRetryableError(error: Error, shouldRetry: Date | boolean) { (error as DecoratedError)[code] = CODE_RETRYABLE; (error as DecoratedError)[retry] = shouldRetry; - return error; -} - -export function throwRetryableError(error: Error, shouldRetry: Date | boolean) { - throw createRetryableError(error, shouldRetry); + throw error; } export function isSkipError(error: Error | DecoratedError) { @@ -74,6 +78,14 @@ export function createSkipError(error: Error): DecoratedError { return error; } +export function createTaskRunError( + error: Error, + errorSource = TaskErrorSource.FRAMEWORK +): DecoratedError { + (error as DecoratedError)[source] = errorSource; + return error; +} + export function isEphemeralTaskRejectedDueToCapacityError( error: Error | EphemeralTaskRejectedDueToCapacityError ) { diff --git a/x-pack/plugins/task_manager/server/task_running/task_runner.test.ts b/x-pack/plugins/task_manager/server/task_running/task_runner.test.ts index 1ae176d6993b3..f59a88400fb53 100644 --- a/x-pack/plugins/task_manager/server/task_running/task_runner.test.ts +++ b/x-pack/plugins/task_manager/server/task_running/task_runner.test.ts @@ -9,7 +9,13 @@ import _ from 'lodash'; import sinon from 'sinon'; import { secondsFromNow } from '../lib/intervals'; import { asOk, asErr } from '../lib/result_type'; -import { TaskManagerRunner, TaskRunningStage, TaskRunResult } from '.'; +import { + createTaskRunError, + TaskErrorSource, + TaskManagerRunner, + TaskRunningStage, + TaskRunResult, +} from '.'; import { TaskEvent, asTaskRunEvent, @@ -1393,7 +1399,7 @@ describe('TaskManagerRunner', () => { ); }); - test('emits TaskEvent when a recurring task returns a success result with hasError=true', async () => { + test('emits TaskEvent when a recurring task returns a success result with taskRunError', async () => { const id = _.random(1, 20).toString(); const runAt = minutesFromNow(_.random(5)); const onTaskEvent = jest.fn(); @@ -1408,7 +1414,11 @@ describe('TaskManagerRunner', () => { title: 'Bar!', createTaskRunner: () => ({ async run() { - return { runAt, state: {}, hasError: true }; + return { + runAt, + state: {}, + taskRunError: createTaskRunError(new Error('test'), TaskErrorSource.FRAMEWORK), + }; }, }), }, @@ -1433,7 +1443,7 @@ describe('TaskManagerRunner', () => { ); }); - test('emits TaskEvent when a recurring task returns a success result with hasError=true but completes after timeout', async () => { + test('emits TaskEvent when a recurring task returns a success result with taskRunError but completes after timeout', async () => { fakeTimer = sinon.useFakeTimers(new Date(2023, 1, 1, 0, 0, 0, 0).valueOf()); const id = _.random(1, 20).toString(); const runAt = minutesFromNow(_.random(5)); @@ -1450,7 +1460,11 @@ describe('TaskManagerRunner', () => { timeout: `1s`, createTaskRunner: () => ({ async run() { - return { runAt, state: {}, hasError: true }; + return { + runAt, + state: {}, + taskRunError: createTaskRunError(new Error('test'), TaskErrorSource.FRAMEWORK), + }; }, }), }, @@ -2061,6 +2075,8 @@ describe('TaskManagerRunner', () => { }); test('does not resets skip attempts for a recurring task as long as there is an error', async () => { + const taskRunError = createTaskRunError(new Error('test'), TaskErrorSource.FRAMEWORK); + const mockTaskInstance: Partial = { schedule: { interval: '10m' }, status: TaskStatus.Running, @@ -2086,7 +2102,10 @@ describe('TaskManagerRunner', () => { return { data: { indirectParams: { foo: 'bar' } } }; }, async run() { - return { state: {}, hasError: true }; + return { + state: {}, + taskRunError, + }; }, }), indirectParamsSchema: schema.object({ @@ -2103,7 +2122,12 @@ describe('TaskManagerRunner', () => { const instance = store.update.mock.calls[0][0]; expect(instance.numSkippedRuns).toBe(mockTaskInstance.numSkippedRuns); expect(logger.warn).not.toHaveBeenCalled(); - expect(result).toEqual(asOk({ state: {}, hasError: true })); + expect(result).toEqual( + asOk({ + state: {}, + taskRunError, + }) + ); }); test('does not resets skip attempts for a non-recurring task as long as there is an error', async () => { @@ -2212,6 +2236,8 @@ describe('TaskManagerRunner', () => { }); test('stops skipping when the max skip limit is reached', async () => { + const taskRunError = createTaskRunError(new Error('test'), TaskErrorSource.FRAMEWORK); + const mockTaskInstance: Partial = { status: TaskStatus.Running, startedAt: new Date(), @@ -2238,7 +2264,10 @@ describe('TaskManagerRunner', () => { return { data: { indirectParams: { baz: 'bar' } } }; }, async run() { - return { state: {}, hasError: true }; + return { + state: {}, + taskRunError, + }; }, }), indirectParamsSchema: schema.object({ @@ -2267,7 +2296,12 @@ describe('TaskManagerRunner', () => { expect(logger.warn).toHaveBeenCalledWith( 'Task Manager has reached the max skip attempts for task bar/foo' ); - expect(result).toEqual(asOk({ state: {}, hasError: true })); + expect(result).toEqual( + asOk({ + state: {}, + taskRunError, + }) + ); }); }); }); diff --git a/x-pack/plugins/task_manager/server/task_running/task_runner.ts b/x-pack/plugins/task_manager/server/task_running/task_runner.ts index 63f520ade1031..62cb733980e57 100644 --- a/x-pack/plugins/task_manager/server/task_running/task_runner.ts +++ b/x-pack/plugins/task_manager/server/task_running/task_runner.ts @@ -664,12 +664,12 @@ export class TaskManagerRunner implements TaskRunner { skipAttempts, }: SuccessfulRunResult & { attempts: number; skipAttempts: number }) => { const { startedAt, schedule, numSkippedRuns } = this.instance.task; - const { hasError } = unwrap(result); + const { taskRunError } = unwrap(result); let requeueInvalidTaskAttempts = skipAttempts || numSkippedRuns || 0; // Alerting TaskRunner returns SuccessResult even though there is an error - // therefore we use "hasError" to be sure that there wasn't any error - if (isUndefined(skipAttempts) && !hasError) { + // therefore we use "taskRunError" to be sure that there wasn't any error + if (isUndefined(skipAttempts) && taskRunError === undefined) { requeueInvalidTaskAttempts = 0; } @@ -747,7 +747,7 @@ export class TaskManagerRunner implements TaskRunner { await eitherAsync( result, - async ({ runAt, schedule, hasError }: SuccessfulRunResult) => { + async ({ runAt, schedule, taskRunError }: SuccessfulRunResult) => { const processedResult = { task, persistence: @@ -757,10 +757,11 @@ export class TaskManagerRunner implements TaskRunner { : this.processResultWhenDone()), }; - // Alerting task runner returns SuccessfulRunResult with hasError=true + // Alerting task runner returns SuccessfulRunResult with taskRunError // when the alerting task fails, so we check for this condition in order // to emit the correct task run event for metrics collection - const taskRunEvent = hasError + // taskRunError contains the "source" (TaskErrorSource) data + const taskRunEvent = !!taskRunError ? asTaskRunEvent( this.id, asErr({ @@ -804,7 +805,6 @@ export class TaskManagerRunner implements TaskRunner { } ); } - return result; } diff --git a/x-pack/plugins/telemetry_collection_xpack/server/index.ts b/x-pack/plugins/telemetry_collection_xpack/server/index.ts index aab1bdb58fe59..85a3adc243236 100644 --- a/x-pack/plugins/telemetry_collection_xpack/server/index.ts +++ b/x-pack/plugins/telemetry_collection_xpack/server/index.ts @@ -5,13 +5,12 @@ * 2.0. */ -import { TelemetryCollectionXpackPlugin } from './plugin'; - export type { ESLicense } from './telemetry_collection'; // This exports static code and TypeScript types, // as well as, Kibana Platform `plugin()` initializer. -export function plugin() { +export async function plugin() { + const { TelemetryCollectionXpackPlugin } = await import('./plugin'); return new TelemetryCollectionXpackPlugin(); } diff --git a/x-pack/plugins/threat_intelligence/server/index.ts b/x-pack/plugins/threat_intelligence/server/index.ts index c658a352a6077..ac4810ed94803 100644 --- a/x-pack/plugins/threat_intelligence/server/index.ts +++ b/x-pack/plugins/threat_intelligence/server/index.ts @@ -6,8 +6,8 @@ */ import { PluginInitializerContext } from '@kbn/core/server'; -import { ThreatIntelligencePlugin } from './plugin'; -export const plugin = (context: PluginInitializerContext) => { +export const plugin = async (context: PluginInitializerContext) => { + const { ThreatIntelligencePlugin } = await import('./plugin'); return new ThreatIntelligencePlugin(context); }; diff --git a/x-pack/plugins/timelines/server/index.ts b/x-pack/plugins/timelines/server/index.ts index c1f4c17e7d757..acdcc26a0a1aa 100644 --- a/x-pack/plugins/timelines/server/index.ts +++ b/x-pack/plugins/timelines/server/index.ts @@ -6,9 +6,9 @@ */ import { PluginInitializerContext } from '@kbn/core/server'; -import { TimelinesPlugin } from './plugin'; -export function plugin(initializerContext: PluginInitializerContext) { +export async function plugin(initializerContext: PluginInitializerContext) { + const { TimelinesPlugin } = await import('./plugin'); return new TimelinesPlugin(initializerContext); } diff --git a/x-pack/plugins/transform/common/api_schemas/audit_messages.ts b/x-pack/plugins/transform/common/api_schemas/audit_messages.ts index 438310f495e70..5027dba58f05c 100644 --- a/x-pack/plugins/transform/common/api_schemas/audit_messages.ts +++ b/x-pack/plugins/transform/common/api_schemas/audit_messages.ts @@ -5,9 +5,20 @@ * 2.0. */ +import { schema, TypeOf } from '@kbn/config-schema'; + import { TransformMessage } from '../types/messages'; export interface GetTransformsAuditMessagesResponseSchema { messages: TransformMessage[]; total: number; } + +export const getTransformAuditMessagesQuerySchema = schema.object({ + sortField: schema.string(), + sortDirection: schema.oneOf([schema.literal('asc'), schema.literal('desc')]), +}); + +export type GetTransformAuditMessagesQuerySchema = TypeOf< + typeof getTransformAuditMessagesQuerySchema +>; diff --git a/x-pack/plugins/transform/common/api_schemas/transforms.ts b/x-pack/plugins/transform/common/api_schemas/transforms.ts index 65e0433a81264..5b1d68bb2d3f7 100644 --- a/x-pack/plugins/transform/common/api_schemas/transforms.ts +++ b/x-pack/plugins/transform/common/api_schemas/transforms.ts @@ -148,16 +148,29 @@ export interface PutTransformsPivotRequestSchema export type PutTransformsLatestRequestSchema = Omit; +export const putTransformsQuerySchema = schema.object({ + createDataView: schema.boolean({ defaultValue: false }), + timeFieldName: schema.maybe(schema.string()), +}); + +export type PutTransformsQuerySchema = TypeOf; + interface TransformCreated { transform: TransformId; } -interface TransformCreatedError { - id: TransformId; +interface DataViewCreated { + id: string; +} +interface CreatedError { + id: string; error: any; } + export interface PutTransformsResponseSchema { transformsCreated: TransformCreated[]; - errors: TransformCreatedError[]; + dataViewsCreated: DataViewCreated[]; + dataViewsErrors: CreatedError[]; + errors: CreatedError[]; } // POST transforms/_preview diff --git a/x-pack/plugins/transform/common/constants.ts b/x-pack/plugins/transform/common/constants.ts index ec26333a834a7..8ee030b2a953d 100644 --- a/x-pack/plugins/transform/common/constants.ts +++ b/x-pack/plugins/transform/common/constants.ts @@ -216,3 +216,5 @@ export const DEFAULT_TRANSFORM_SETTINGS_MAX_PAGE_SEARCH_SIZE = 500; // Used in the transform list's expanded row for the messages and issues table. export const TIME_FORMAT = 'YYYY-MM-DD HH:mm:ss'; + +export const TRANSFORM_NOTIFICATIONS_INDEX = '.transform-notifications-read'; diff --git a/x-pack/plugins/transform/common/types/transform.ts b/x-pack/plugins/transform/common/types/transform.ts index 8c6690641873a..2e244e69b70fa 100644 --- a/x-pack/plugins/transform/common/types/transform.ts +++ b/x-pack/plugins/transform/common/types/transform.ts @@ -70,3 +70,12 @@ export interface LatestFunctionConfigUI { unique_key: Array> | undefined; sort: EuiComboBoxOptionOption | undefined; } + +export enum TRANSFORM_ACTIONS { + DELETE = 'delete', + REAUTHORIZE = 'reauthorize', + RESET = 'reset', + SCHEDULE_NOW = 'schedule_now', + STOP = 'stop', + START = 'start', +} diff --git a/x-pack/plugins/transform/public/app/hooks/use_create_transform.tsx b/x-pack/plugins/transform/public/app/hooks/use_create_transform.tsx index 272e815c42eb4..c678549683bec 100644 --- a/x-pack/plugins/transform/public/app/hooks/use_create_transform.tsx +++ b/x-pack/plugins/transform/public/app/hooks/use_create_transform.tsx @@ -27,6 +27,8 @@ import { useRefreshTransformList } from './use_refresh_transform_list'; interface CreateTransformArgs { transformId: TransformId; transformConfig: PutTransformsRequestSchema; + createDataView: boolean; + timeFieldName?: string; } export const useCreateTransform = () => { @@ -48,10 +50,16 @@ export const useCreateTransform = () => { } const mutation = useMutation({ - mutationFn: ({ transformId, transformConfig }: CreateTransformArgs) => { + mutationFn: ({ + transformId, + transformConfig, + createDataView = false, + timeFieldName, + }: CreateTransformArgs) => { return http.put( addInternalBasePath(`transforms/${transformId}`), { + query: { createDataView, timeFieldName }, body: JSON.stringify(transformConfig), version: '1', } diff --git a/x-pack/plugins/transform/public/app/sections/create_transform/components/step_create/step_create_form.tsx b/x-pack/plugins/transform/public/app/sections/create_transform/components/step_create/step_create_form.tsx index 3c78757a6f257..07eb6e536ade3 100644 --- a/x-pack/plugins/transform/public/app/sections/create_transform/components/step_create/step_create_form.tsx +++ b/x-pack/plugins/transform/public/app/sections/create_transform/components/step_create/step_create_form.tsx @@ -28,9 +28,6 @@ import { toMountPoint } from '@kbn/react-kibana-mount'; import { DISCOVER_APP_LOCATOR } from '@kbn/discover-plugin/common'; -import { DuplicateDataViewError } from '@kbn/data-plugin/public'; -import type { RuntimeField } from '@kbn/data-views-plugin/common'; -import { isPopulatedObject } from '@kbn/ml-is-populated-object'; import { PROGRESS_REFRESH_INTERVAL_MS } from '../../../../../../common/constants'; import { getErrorMessage } from '../../../../../../common/utils/errors'; @@ -44,7 +41,7 @@ import { PutTransformsLatestRequestSchema, PutTransformsPivotRequestSchema, } from '../../../../../../common/api_schemas/transforms'; -import { isContinuousTransform, isLatestTransform } from '../../../../../../common/types/transform'; +import { isContinuousTransform } from '../../../../../../common/types/transform'; import { TransformAlertFlyout } from '../../../../../alerting/transform_alerting_flyout'; export interface StepDetailsExposedState { @@ -87,8 +84,7 @@ export const StepCreateForm: FC = React.memo( const [discoverLink, setDiscoverLink] = useState(); const toastNotifications = useToastNotifications(); - const { application, data, i18n: i18nStart, share, theme } = useAppDependencies(); - const dataViews = data.dataViews; + const { application, i18n: i18nStart, share, theme } = useAppDependencies(); const isDiscoverAvailable = application.capabilities.discover?.show ?? false; useEffect(() => { @@ -128,13 +124,13 @@ export const StepCreateForm: FC = React.memo( setLoading(true); createTransform( - { transformId, transformConfig }, + { transformId, transformConfig, createDataView, timeFieldName }, { onError: () => setCreated(false), - onSuccess: () => { + onSuccess: (resp) => { setCreated(true); - if (createDataView) { - createKibanaDataView(); + if (resp.dataViewsCreated.length === 1) { + setDataViewId(resp.dataViewsCreated[0].id); } if (startAfterCreation) { startTransform(); @@ -155,57 +151,6 @@ export const StepCreateForm: FC = React.memo( }); } - const createKibanaDataView = async () => { - setLoading(true); - const dataViewName = transformConfig.dest.index; - const runtimeMappings = transformConfig.source.runtime_mappings as Record< - string, - RuntimeField - >; - - try { - const newDataView = await dataViews.createAndSave( - { - title: dataViewName, - timeFieldName, - ...(isPopulatedObject(runtimeMappings) && isLatestTransform(transformConfig) - ? { runtimeFieldMap: runtimeMappings } - : {}), - allowNoIndex: true, - }, - false, - true - ); - - setDataViewId(newDataView.id); - setLoading(false); - return true; - } catch (e) { - if (e instanceof DuplicateDataViewError) { - toastNotifications.addDanger( - i18n.translate('xpack.transform.stepCreateForm.duplicateDataViewErrorMessage', { - defaultMessage: - 'An error occurred creating the Kibana data view {dataViewName}: The data view already exists.', - values: { dataViewName }, - }) - ); - } else { - toastNotifications.addDanger({ - title: i18n.translate('xpack.transform.stepCreateForm.createDataViewErrorMessage', { - defaultMessage: 'An error occurred creating the Kibana data view {dataViewName}:', - values: { dataViewName }, - }), - text: toMountPoint(, { - theme, - i18n: i18nStart, - }), - }); - setLoading(false); - return false; - } - } - }; - const isBatchTransform = typeof transformConfig.sync === 'undefined'; useEffect(() => { diff --git a/x-pack/plugins/transform/server/index.ts b/x-pack/plugins/transform/server/index.ts index 0688210a78137..2ae5ffbd3ccdf 100644 --- a/x-pack/plugins/transform/server/index.ts +++ b/x-pack/plugins/transform/server/index.ts @@ -7,8 +7,9 @@ import { PluginInitializerContext } from '@kbn/core/server'; -import { TransformServerPlugin } from './plugin'; - -export const plugin = (ctx: PluginInitializerContext) => new TransformServerPlugin(ctx); +export const plugin = async (ctx: PluginInitializerContext) => { + const { TransformServerPlugin } = await import('./plugin'); + return new TransformServerPlugin(ctx); +}; export { registerTransformHealthRuleType } from './lib/alerting'; diff --git a/x-pack/plugins/transform/server/lib/alerting/transform_health_rule_type/transform_health_service.ts b/x-pack/plugins/transform/server/lib/alerting/transform_health_rule_type/transform_health_service.ts index 5c218a40abb45..8bf3fb16f6a0f 100644 --- a/x-pack/plugins/transform/server/lib/alerting/transform_health_rule_type/transform_health_service.ts +++ b/x-pack/plugins/transform/server/lib/alerting/transform_health_rule_type/transform_health_service.ts @@ -16,6 +16,7 @@ import { TransformHealthRuleParams } from './schema'; import { ALL_TRANSFORMS_SELECTION, TRANSFORM_HEALTH_CHECK_NAMES, + TRANSFORM_NOTIFICATIONS_INDEX, TRANSFORM_RULE_TYPE, TRANSFORM_STATE, } from '../../../../common/constants'; @@ -27,7 +28,6 @@ import type { } from './register_transform_health_rule_type'; import type { TransformHealthAlertRule } from '../../../../common/types/alerting'; import { isContinuousTransform } from '../../../../common/types/transform'; -import { ML_DF_NOTIFICATION_INDEX_PATTERN } from '../../../routes/api/transforms_audit_messages'; interface TestResult { isHealthy: boolean; @@ -169,7 +169,7 @@ export function transformHealthServiceProvider({ unknown, Record<'by_transform', estypes.AggregationsMultiBucketAggregateBase> >({ - index: ML_DF_NOTIFICATION_INDEX_PATTERN, + index: TRANSFORM_NOTIFICATIONS_INDEX, size: 0, query: { bool: { diff --git a/x-pack/plugins/transform/server/routes/api/audit_messages/register_route.ts b/x-pack/plugins/transform/server/routes/api/audit_messages/register_route.ts new file mode 100644 index 0000000000000..be665d9acc890 --- /dev/null +++ b/x-pack/plugins/transform/server/routes/api/audit_messages/register_route.ts @@ -0,0 +1,53 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { addInternalBasePath } from '../../../../common/constants'; +import { + transformIdParamSchema, + TransformIdParamSchema, +} from '../../../../common/api_schemas/common'; +import { + getTransformAuditMessagesQuerySchema, + type GetTransformAuditMessagesQuerySchema, +} from '../../../../common/api_schemas/audit_messages'; + +import { RouteDependencies } from '../../../types'; + +import { routeHandler } from './route_handler'; + +export function registerRoute({ router, license }: RouteDependencies) { + /** + * @apiGroup Transforms Audit Messages + * + * @api {get} /internal/transform/transforms/:transformId/messages Transforms Messages + * @apiName GetTransformsMessages + * @apiDescription Get transforms audit messages + * + * @apiSchema (params) transformIdParamSchema + */ + router.versioned + .get({ + path: addInternalBasePath('transforms/{transformId}/messages'), + access: 'internal', + }) + .addVersion( + { + version: '1', + validate: { + request: { + params: transformIdParamSchema, + query: getTransformAuditMessagesQuerySchema, + }, + }, + }, + license.guardApiRoute< + TransformIdParamSchema, + GetTransformAuditMessagesQuerySchema, + undefined + >(routeHandler) + ); +} diff --git a/x-pack/plugins/transform/server/routes/api/audit_messages/route_handler.ts b/x-pack/plugins/transform/server/routes/api/audit_messages/route_handler.ts new file mode 100644 index 0000000000000..81d1ee01645d5 --- /dev/null +++ b/x-pack/plugins/transform/server/routes/api/audit_messages/route_handler.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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type { RequestHandler } from '@kbn/core/server'; + +import { + DEFAULT_MAX_AUDIT_MESSAGE_SIZE, + TRANSFORM_NOTIFICATIONS_INDEX, +} from '../../../../common/constants'; +import type { TransformIdParamSchema } from '../../../../common/api_schemas/common'; +import { AuditMessage } from '../../../../common/types/messages'; + +import { wrapError, wrapEsError } from '../../utils/error_utils'; + +interface BoolQuery { + bool: { [key: string]: any }; +} + +interface TransformMessageQuery { + sortField: string; + sortDirection: 'asc' | 'desc'; +} + +export const routeHandler: RequestHandler< + TransformIdParamSchema, + TransformMessageQuery, + undefined +> = async (ctx, req, res) => { + const { transformId } = req.params; + const sortField = req.query?.sortField ?? 'timestamp'; + const sortDirection = req.query?.sortDirection ?? 'desc'; + + // search for audit messages, + // transformId is optional. without it, all transforms will be listed. + const query: BoolQuery = { + bool: { + filter: [ + { + bool: { + must_not: { + term: { + level: 'activity', + }, + }, + }, + }, + ], + }, + }; + + // if no transformId specified, load all of the messages + if (transformId !== undefined) { + query.bool.filter.push({ + bool: { + should: [ + { + term: { + transform_id: '', // catch system messages + }, + }, + { + term: { + transform_id: transformId, // messages for specified transformId + }, + }, + ], + }, + }); + } + + try { + const esClient = (await ctx.core).elasticsearch.client; + const resp = await esClient.asCurrentUser.search({ + index: TRANSFORM_NOTIFICATIONS_INDEX, + ignore_unavailable: true, + size: DEFAULT_MAX_AUDIT_MESSAGE_SIZE, + body: { + sort: [ + { [sortField]: { order: sortDirection } }, + { transform_id: { order: 'asc' as const } }, + ], + query, + }, + track_total_hits: true, + }); + const totalHits = + typeof resp.hits.total === 'number' ? resp.hits.total : resp.hits.total!.value; + + let messages: AuditMessage[] = []; + // TODO: remove typeof checks when appropriate overloading is added for the `search` API + if ( + (typeof resp.hits.total === 'number' && resp.hits.total > 0) || + (typeof resp.hits.total === 'object' && resp.hits.total.value > 0) + ) { + messages = resp.hits.hits.map((hit) => hit._source!); + } + return res.ok({ body: { messages, total: totalHits } }); + } catch (e) { + return res.customError(wrapError(wrapEsError(e))); + } +}; diff --git a/x-pack/plugins/transform/server/routes/api/delete_transforms/delete_transforms.ts b/x-pack/plugins/transform/server/routes/api/delete_transforms/delete_transforms.ts new file mode 100644 index 0000000000000..00c0f4b40acfb --- /dev/null +++ b/x-pack/plugins/transform/server/routes/api/delete_transforms/delete_transforms.ts @@ -0,0 +1,133 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type { KibanaResponseFactory, RequestHandlerContext } from '@kbn/core/server'; +import type { DataViewsService } from '@kbn/data-views-plugin/common'; + +import { TRANSFORM_ACTIONS } from '../../../../common/types/transform'; +import { TRANSFORM_STATE } from '../../../../common/constants'; +import type { ResponseStatus } from '../../../../common/api_schemas/common'; +import type { + DeleteTransformsRequestSchema, + DeleteTransformsResponseSchema, +} from '../../../../common/api_schemas/delete_transforms'; + +import { isRequestTimeout, fillResultsWithTimeouts } from '../../utils/error_utils'; + +async function getDataViewId(indexName: string, dataViewsService: DataViewsService) { + const dv = (await dataViewsService.find(indexName)).find(({ title }) => title === indexName); + return dv?.id; +} + +async function deleteDestDataViewById(dataViewId: string, dataViewsService: DataViewsService) { + return await dataViewsService.delete(dataViewId); +} + +export async function deleteTransforms( + reqBody: DeleteTransformsRequestSchema, + ctx: RequestHandlerContext, + response: KibanaResponseFactory, + dataViewsService: DataViewsService +) { + const { transformsInfo } = reqBody; + + // Cast possible undefineds as booleans + const deleteDestIndex = !!reqBody.deleteDestIndex; + const deleteDestDataView = !!reqBody.deleteDestDataView; + const shouldForceDelete = !!reqBody.forceDelete; + + const results: DeleteTransformsResponseSchema = {}; + + const coreContext = await ctx.core; + const esClient = coreContext.elasticsearch.client; + + for (const transformInfo of transformsInfo) { + let destinationIndex: string | undefined; + + const transformDeleted: ResponseStatus = { success: false }; + const destIndexDeleted: ResponseStatus = { success: false }; + const destDataViewDeleted: ResponseStatus = { + success: false, + }; + const transformId = transformInfo.id; + // force delete only if the transform has failed + let needToForceDelete = false; + + try { + if (transformInfo.state === TRANSFORM_STATE.FAILED) { + needToForceDelete = true; + } + if (!shouldForceDelete) { + // Grab destination index info to delete + try { + const body = await esClient.asCurrentUser.transform.getTransform({ + transform_id: transformId, + }); + const transformConfig = body.transforms[0]; + destinationIndex = transformConfig.dest.index; + } catch (getTransformConfigError) { + transformDeleted.error = getTransformConfigError.meta.body.error; + results[transformId] = { + transformDeleted, + destIndexDeleted, + destDataViewDeleted, + destinationIndex, + }; + // No need to perform further delete attempts + continue; + } + } + + // Delete the data view if there's a data view that matches the name of dest index + if (destinationIndex && deleteDestDataView) { + try { + const dataViewId = await getDataViewId(destinationIndex, dataViewsService); + if (dataViewId) { + await deleteDestDataViewById(dataViewId, dataViewsService); + destDataViewDeleted.success = true; + } + } catch (deleteDestDataViewError) { + destDataViewDeleted.error = deleteDestDataViewError.meta.body.error; + } + } + + try { + await esClient.asCurrentUser.transform.deleteTransform({ + transform_id: transformId, + force: shouldForceDelete && needToForceDelete, + // @ts-expect-error ES type needs to be updated + delete_dest_index: deleteDestIndex, + }); + transformDeleted.success = true; + destIndexDeleted.success = deleteDestIndex; + } catch (deleteTransformJobError) { + transformDeleted.error = deleteTransformJobError.meta.body.error; + if (deleteTransformJobError.statusCode === 403) { + return response.forbidden(); + } + } + + results[transformId] = { + transformDeleted, + destIndexDeleted, + destDataViewDeleted, + destinationIndex, + }; + } catch (e) { + if (isRequestTimeout(e)) { + return fillResultsWithTimeouts({ + results, + id: transformInfo.id, + items: transformsInfo, + action: TRANSFORM_ACTIONS.DELETE, + }); + } + results[transformId] = { transformDeleted: { success: false, error: e.meta.body.error } }; + } + } + return results; +} diff --git a/x-pack/plugins/transform/server/routes/api/delete_transforms/register_route.ts b/x-pack/plugins/transform/server/routes/api/delete_transforms/register_route.ts new file mode 100644 index 0000000000000..cdb58c02d9664 --- /dev/null +++ b/x-pack/plugins/transform/server/routes/api/delete_transforms/register_route.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 { + deleteTransformsRequestSchema, + type DeleteTransformsRequestSchema, +} from '../../../../common/api_schemas/delete_transforms'; +import { addInternalBasePath } from '../../../../common/constants'; + +import type { RouteDependencies } from '../../../types'; + +import { routeHandlerFactory } from './route_handler_factory'; + +export function registerRoute(routeDependencies: RouteDependencies) { + const { router, license } = routeDependencies; + /** + * @apiGroup Transforms + * + * @api {post} /internal/transform/delete_transforms Post delete transforms + * @apiName DeleteTransforms + * @apiDescription Deletes transforms + * + * @apiSchema (body) deleteTransformsRequestSchema + */ + router.versioned + .post({ + path: addInternalBasePath('delete_transforms'), + access: 'internal', + }) + .addVersion( + { + version: '1', + validate: { + request: { + body: deleteTransformsRequestSchema, + }, + }, + }, + license.guardApiRoute( + routeHandlerFactory(routeDependencies) + ) + ); +} diff --git a/x-pack/plugins/transform/server/routes/api/delete_transforms/route_handler_factory.ts b/x-pack/plugins/transform/server/routes/api/delete_transforms/route_handler_factory.ts new file mode 100644 index 0000000000000..81b51cabb6209 --- /dev/null +++ b/x-pack/plugins/transform/server/routes/api/delete_transforms/route_handler_factory.ts @@ -0,0 +1,56 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type { RequestHandler } from '@kbn/core/server'; + +import { type DeleteTransformsRequestSchema } from '../../../../common/api_schemas/delete_transforms'; + +import type { TransformRequestHandlerContext } from '../../../services/license'; +import { RouteDependencies } from '../../../types'; + +import { wrapError, wrapEsError } from '../../utils/error_utils'; + +import { deleteTransforms } from './delete_transforms'; + +export const routeHandlerFactory: ( + routeDependencies: RouteDependencies +) => RequestHandler< + undefined, + undefined, + DeleteTransformsRequestSchema, + TransformRequestHandlerContext +> = + ({ coreStart, dataViews }) => + async (ctx, req, res) => { + try { + const { savedObjects, elasticsearch } = coreStart; + const savedObjectsClient = savedObjects.getScopedClient(req); + const esClient = elasticsearch.client.asScoped(req).asCurrentUser; + + const dataViewsService = await dataViews.dataViewsServiceFactory( + savedObjectsClient, + esClient, + req + ); + const body = await deleteTransforms(req.body, ctx, res, dataViewsService); + + if (body && body.status) { + if (body.status === 404) { + return res.notFound(); + } + if (body.status === 403) { + return res.forbidden(); + } + } + + return res.ok({ + body, + }); + } catch (e) { + return res.customError(wrapError(wrapEsError(e))); + } + }; diff --git a/x-pack/plugins/transform/server/routes/api/field_histograms.ts b/x-pack/plugins/transform/server/routes/api/field_histograms.ts deleted file mode 100644 index 39020201bdd6f..0000000000000 --- a/x-pack/plugins/transform/server/routes/api/field_histograms.ts +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { fetchHistogramsForFields } from '@kbn/ml-agg-utils'; -import { addInternalBasePath } from '../../../common/constants'; - -import { dataViewTitleSchema, DataViewTitleSchema } from '../../../common/api_schemas/common'; -import { - fieldHistogramsRequestSchema, - FieldHistogramsRequestSchema, -} from '../../../common/api_schemas/field_histograms'; -import { RouteDependencies } from '../../types'; - -import { wrapError, wrapEsError } from './error_utils'; - -export function registerFieldHistogramsRoutes({ router, license }: RouteDependencies) { - router.versioned - .post({ - path: addInternalBasePath('field_histograms/{dataViewTitle}'), - access: 'internal', - }) - .addVersion( - { - version: '1', - validate: { - request: { - params: dataViewTitleSchema, - body: fieldHistogramsRequestSchema, - }, - }, - }, - license.guardApiRoute( - async (ctx, req, res) => { - const { dataViewTitle } = req.params; - const { query, fields, runtimeMappings, samplerShardSize } = req.body; - - try { - const esClient = (await ctx.core).elasticsearch.client; - const resp = await fetchHistogramsForFields( - esClient.asCurrentUser, - dataViewTitle, - query, - fields, - samplerShardSize, - runtimeMappings - ); - - return res.ok({ body: resp }); - } catch (e) { - return res.customError(wrapError(wrapEsError(e))); - } - } - ) - ); -} diff --git a/x-pack/plugins/transform/server/routes/api/field_histograms/register_route.ts b/x-pack/plugins/transform/server/routes/api/field_histograms/register_route.ts new file mode 100644 index 0000000000000..5cba0b49675da --- /dev/null +++ b/x-pack/plugins/transform/server/routes/api/field_histograms/register_route.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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { addInternalBasePath } from '../../../../common/constants'; + +import { dataViewTitleSchema, DataViewTitleSchema } from '../../../../common/api_schemas/common'; +import { + fieldHistogramsRequestSchema, + FieldHistogramsRequestSchema, +} from '../../../../common/api_schemas/field_histograms'; +import { RouteDependencies } from '../../../types'; + +import { routeHandler } from './route_handler'; + +export function registerRoute({ router, license }: RouteDependencies) { + router.versioned + .post({ + path: addInternalBasePath('field_histograms/{dataViewTitle}'), + access: 'internal', + }) + .addVersion( + { + version: '1', + validate: { + request: { + params: dataViewTitleSchema, + body: fieldHistogramsRequestSchema, + }, + }, + }, + license.guardApiRoute( + routeHandler + ) + ); +} diff --git a/x-pack/plugins/transform/server/routes/api/field_histograms/route_handler.ts b/x-pack/plugins/transform/server/routes/api/field_histograms/route_handler.ts new file mode 100644 index 0000000000000..365813860462a --- /dev/null +++ b/x-pack/plugins/transform/server/routes/api/field_histograms/route_handler.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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type { RequestHandler } from '@kbn/core/server'; +import { fetchHistogramsForFields } from '@kbn/ml-agg-utils'; + +import type { DataViewTitleSchema } from '../../../../common/api_schemas/common'; +import type { FieldHistogramsRequestSchema } from '../../../../common/api_schemas/field_histograms'; + +import { wrapError, wrapEsError } from '../../utils/error_utils'; + +export const routeHandler: RequestHandler< + DataViewTitleSchema, + undefined, + FieldHistogramsRequestSchema +> = async (ctx, req, res) => { + const { dataViewTitle } = req.params; + const { query, fields, runtimeMappings, samplerShardSize } = req.body; + + try { + const esClient = (await ctx.core).elasticsearch.client; + const resp = await fetchHistogramsForFields( + esClient.asCurrentUser, + dataViewTitle, + query, + fields, + samplerShardSize, + runtimeMappings + ); + + return res.ok({ body: resp }); + } catch (e) { + return res.customError(wrapError(wrapEsError(e))); + } +}; diff --git a/x-pack/plugins/transform/server/routes/api/reauthorize_transforms/reauthorize_and_start_transforms.ts b/x-pack/plugins/transform/server/routes/api/reauthorize_transforms/reauthorize_and_start_transforms.ts new file mode 100644 index 0000000000000..45d78999223a1 --- /dev/null +++ b/x-pack/plugins/transform/server/routes/api/reauthorize_transforms/reauthorize_and_start_transforms.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 type { ElasticsearchClient } from '@kbn/core/server'; +import type { TransportRequestOptions } from '@elastic/elasticsearch'; + +import { TRANSFORM_ACTIONS } from '../../../../common/types/transform'; +import type { + ReauthorizeTransformsRequestSchema, + ReauthorizeTransformsResponseSchema, +} from '../../../../common/api_schemas/reauthorize_transforms'; + +import { isRequestTimeout, fillResultsWithTimeouts } from '../../utils/error_utils'; + +export async function reauthorizeAndStartTransforms( + transformsInfo: ReauthorizeTransformsRequestSchema, + esClient: ElasticsearchClient, + options?: TransportRequestOptions +) { + const results: ReauthorizeTransformsResponseSchema = {}; + + for (const transformInfo of transformsInfo) { + const transformId = transformInfo.id; + try { + await esClient.transform.updateTransform( + { + body: {}, + transform_id: transformId, + }, + options ?? {} + ); + + await esClient.transform.startTransform( + { + transform_id: transformId, + }, + { ignore: [409] } + ); + + results[transformId] = { success: true }; + } catch (e) { + if (isRequestTimeout(e)) { + return fillResultsWithTimeouts({ + results, + id: transformId, + items: transformsInfo, + action: TRANSFORM_ACTIONS.REAUTHORIZE, + }); + } + results[transformId] = { success: false, error: e.meta.body.error }; + } + } + return results; +} diff --git a/x-pack/plugins/transform/server/routes/api/reauthorize_transforms/register_route.ts b/x-pack/plugins/transform/server/routes/api/reauthorize_transforms/register_route.ts new file mode 100644 index 0000000000000..017aa98e76304 --- /dev/null +++ b/x-pack/plugins/transform/server/routes/api/reauthorize_transforms/register_route.ts @@ -0,0 +1,45 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type { StartTransformsRequestSchema } from '../../../../common/api_schemas/start_transforms'; +import { reauthorizeTransformsRequestSchema } from '../../../../common/api_schemas/reauthorize_transforms'; +import { addInternalBasePath } from '../../../../common/constants'; + +import type { RouteDependencies } from '../../../types'; + +import { routeHandlerFactory } from './route_handler_factory'; + +export function registerRoute(routeDependencies: RouteDependencies) { + const { router, license } = routeDependencies; + /** + * @apiGroup Reauthorize transforms with API key generated from currently logged in user + * @api {post} /internal/transform/reauthorize_transforms Post reauthorize transforms + * @apiName Reauthorize Transforms + * @apiDescription Reauthorize transforms by generating an API Key for current user + * and update transform's es-secondary-authorization headers with the generated key, + * then start the transform. + * @apiSchema (body) reauthorizeTransformsRequestSchema + */ + router.versioned + .post({ + path: addInternalBasePath('reauthorize_transforms'), + access: 'internal', + }) + .addVersion( + { + version: '1', + validate: { + request: { + body: reauthorizeTransformsRequestSchema, + }, + }, + }, + license.guardApiRoute( + routeHandlerFactory(routeDependencies) + ) + ); +} diff --git a/x-pack/plugins/transform/server/routes/api/reauthorize_transforms/route_handler_factory.ts b/x-pack/plugins/transform/server/routes/api/reauthorize_transforms/route_handler_factory.ts new file mode 100644 index 0000000000000..acefdec0257a9 --- /dev/null +++ b/x-pack/plugins/transform/server/routes/api/reauthorize_transforms/route_handler_factory.ts @@ -0,0 +1,55 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type { RequestHandler } from '@kbn/core/server'; + +import { generateTransformSecondaryAuthHeaders } from '../../../../common/utils/transform_api_key'; +import type { StartTransformsRequestSchema } from '../../../../common/api_schemas/start_transforms'; + +import type { TransformRequestHandlerContext } from '../../../services/license'; + +import type { RouteDependencies } from '../../../types'; + +import { wrapError, wrapEsError } from '../../utils/error_utils'; + +import { reauthorizeAndStartTransforms } from './reauthorize_and_start_transforms'; + +export const routeHandlerFactory: ( + routeDependencies: RouteDependencies +) => RequestHandler< + undefined, + undefined, + StartTransformsRequestSchema, + TransformRequestHandlerContext +> = (routeDependencies) => async (ctx, req, res) => { + const { coreStart, security: securityStart } = routeDependencies; + + try { + const transformsInfo = req.body; + const { elasticsearch } = coreStart; + const esClient = elasticsearch.client.asScoped(req).asCurrentUser; + + let apiKeyWithCurrentUserPermission; + + // If security is not enabled or available, user should not have the need to reauthorize + // in that case, start anyway + if (securityStart) { + apiKeyWithCurrentUserPermission = await securityStart.authc.apiKeys.grantAsInternalUser(req, { + name: `auto-generated-transform-api-key`, + role_descriptors: {}, + }); + } + const secondaryAuth = generateTransformSecondaryAuthHeaders(apiKeyWithCurrentUserPermission); + + const authorizedTransforms = await reauthorizeAndStartTransforms(transformsInfo, esClient, { + ...(secondaryAuth ? secondaryAuth : {}), + }); + return res.ok({ body: authorizedTransforms }); + } catch (e) { + return res.customError(wrapError(wrapEsError(e))); + } +}; diff --git a/x-pack/plugins/transform/server/routes/api/reset_transforms/register_route.ts b/x-pack/plugins/transform/server/routes/api/reset_transforms/register_route.ts new file mode 100644 index 0000000000000..cae6245455810 --- /dev/null +++ b/x-pack/plugins/transform/server/routes/api/reset_transforms/register_route.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. + */ + +import { + resetTransformsRequestSchema, + type ResetTransformsRequestSchema, +} from '../../../../common/api_schemas/reset_transforms'; +import { addInternalBasePath } from '../../../../common/constants'; + +import type { RouteDependencies } from '../../../types'; + +import { routeHandler } from './route_handler'; + +export function registerRoute({ router, license }: RouteDependencies) { + /** + * @apiGroup Transforms + * + * @api {post} /internal/transform/reset_transforms Post reset transforms + * @apiName ResetTransforms + * @apiDescription resets transforms + * + * @apiSchema (body) resetTransformsRequestSchema + */ + router.versioned + .post({ + path: addInternalBasePath('reset_transforms'), + access: 'internal', + }) + .addVersion( + { + version: '1', + validate: { + request: { + body: resetTransformsRequestSchema, + }, + }, + }, + license.guardApiRoute(routeHandler) + ); +} diff --git a/x-pack/plugins/transform/server/routes/api/reset_transforms/reset_transforms.ts b/x-pack/plugins/transform/server/routes/api/reset_transforms/reset_transforms.ts new file mode 100644 index 0000000000000..e9d2edd52f440 --- /dev/null +++ b/x-pack/plugins/transform/server/routes/api/reset_transforms/reset_transforms.ts @@ -0,0 +1,62 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type { KibanaResponseFactory, RequestHandlerContext } from '@kbn/core/server'; + +import { TRANSFORM_ACTIONS } from '../../../../common/types/transform'; +import type { ResponseStatus } from '../../../../common/api_schemas/common'; +import type { + ResetTransformsRequestSchema, + ResetTransformsResponseSchema, +} from '../../../../common/api_schemas/reset_transforms'; + +import { isRequestTimeout, fillResultsWithTimeouts } from '../../utils/error_utils'; + +export async function resetTransforms( + reqBody: ResetTransformsRequestSchema, + ctx: RequestHandlerContext, + response: KibanaResponseFactory +) { + const { transformsInfo } = reqBody; + + const results: ResetTransformsResponseSchema = {}; + const esClient = (await ctx.core).elasticsearch.client; + + for (const transformInfo of transformsInfo) { + const transformReset: ResponseStatus = { success: false }; + const transformId = transformInfo.id; + + try { + try { + await esClient.asCurrentUser.transform.resetTransform({ + transform_id: transformId, + }); + transformReset.success = true; + } catch (resetTransformJobError) { + transformReset.error = resetTransformJobError.meta.body.error; + if (resetTransformJobError.statusCode === 403) { + return response.forbidden(); + } + } + + results[transformId] = { + transformReset, + }; + } catch (e) { + if (isRequestTimeout(e)) { + return fillResultsWithTimeouts({ + results, + id: transformInfo.id, + items: transformsInfo, + action: TRANSFORM_ACTIONS.RESET, + }); + } + results[transformId] = { transformReset: { success: false, error: e.meta.body.error } }; + } + } + return results; +} diff --git a/x-pack/plugins/transform/server/routes/api/reset_transforms/route_handler.ts b/x-pack/plugins/transform/server/routes/api/reset_transforms/route_handler.ts new file mode 100644 index 0000000000000..d10a093ae5ee2 --- /dev/null +++ b/x-pack/plugins/transform/server/routes/api/reset_transforms/route_handler.ts @@ -0,0 +1,42 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type { RequestHandler } from '@kbn/core/server'; + +import type { ResetTransformsRequestSchema } from '../../../../common/api_schemas/reset_transforms'; + +import type { TransformRequestHandlerContext } from '../../../services/license'; + +import { wrapError, wrapEsError } from '../../utils/error_utils'; + +import { resetTransforms } from './reset_transforms'; + +export const routeHandler: RequestHandler< + undefined, + undefined, + ResetTransformsRequestSchema, + TransformRequestHandlerContext +> = async (ctx, req, res) => { + try { + const body = await resetTransforms(req.body, ctx, res); + + if (body && body.status) { + if (body.status === 404) { + return res.notFound(); + } + if (body.status === 403) { + return res.forbidden(); + } + } + + return res.ok({ + body, + }); + } catch (e) { + return res.customError(wrapError(wrapEsError(e))); + } +}; diff --git a/x-pack/plugins/transform/server/routes/api/schedule_now_transforms/register_route.ts b/x-pack/plugins/transform/server/routes/api/schedule_now_transforms/register_route.ts new file mode 100644 index 0000000000000..cf19b56c316f1 --- /dev/null +++ b/x-pack/plugins/transform/server/routes/api/schedule_now_transforms/register_route.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. + */ + +import { + scheduleNowTransformsRequestSchema, + type ScheduleNowTransformsRequestSchema, +} from '../../../../common/api_schemas/schedule_now_transforms'; +import { addInternalBasePath } from '../../../../common/constants'; + +import type { RouteDependencies } from '../../../types'; + +import { routeHandler } from './route_handler'; + +export function registerRoute({ router, license }: RouteDependencies) { + /** + * @apiGroup Transforms + * + * @api {post} /internal/transform/schedule_now_transforms Schedules transforms now + * @apiName PostScheduleNowTransforms + * @apiDescription Schedules transforms now + * + * @apiSchema (body) scheduleNowTransformsRequestSchema + */ + router.versioned + .post({ + path: addInternalBasePath('schedule_now_transforms'), + access: 'internal', + }) + .addVersion( + { + version: '1', + validate: { + request: { + body: scheduleNowTransformsRequestSchema, + }, + }, + }, + license.guardApiRoute(routeHandler) + ); +} diff --git a/x-pack/plugins/transform/server/routes/api/schedule_now_transforms/route_handler.ts b/x-pack/plugins/transform/server/routes/api/schedule_now_transforms/route_handler.ts new file mode 100644 index 0000000000000..53099f7270b7a --- /dev/null +++ b/x-pack/plugins/transform/server/routes/api/schedule_now_transforms/route_handler.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 type { RequestHandler } from '@kbn/core/server'; + +import type { ScheduleNowTransformsRequestSchema } from '../../../../common/api_schemas/schedule_now_transforms'; + +import type { TransformRequestHandlerContext } from '../../../services/license'; + +import { wrapError, wrapEsError } from '../../utils/error_utils'; + +import { scheduleNowTransforms } from './schedule_now_transforms'; + +export const routeHandler: RequestHandler< + undefined, + undefined, + ScheduleNowTransformsRequestSchema, + TransformRequestHandlerContext +> = async (ctx, req, res) => { + const transformsInfo = req.body; + + try { + const esClient = (await ctx.core).elasticsearch.client; + return res.ok({ + body: await scheduleNowTransforms(transformsInfo, esClient.asCurrentUser), + }); + } catch (e) { + return res.customError(wrapError(wrapEsError(e))); + } +}; diff --git a/x-pack/plugins/transform/server/routes/api/schedule_now_transforms/schedule_now_transforms.ts b/x-pack/plugins/transform/server/routes/api/schedule_now_transforms/schedule_now_transforms.ts new file mode 100644 index 0000000000000..fddcaf78185d4 --- /dev/null +++ b/x-pack/plugins/transform/server/routes/api/schedule_now_transforms/schedule_now_transforms.ts @@ -0,0 +1,46 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { ElasticsearchClient } from '@kbn/core/server'; + +import { TRANSFORM_ACTIONS } from '../../../../common/types/transform'; +import type { + ScheduleNowTransformsRequestSchema, + ScheduleNowTransformsResponseSchema, +} from '../../../../common/api_schemas/schedule_now_transforms'; + +import { isRequestTimeout, fillResultsWithTimeouts } from '../../utils/error_utils'; + +export async function scheduleNowTransforms( + transformsInfo: ScheduleNowTransformsRequestSchema, + esClient: ElasticsearchClient +) { + const results: ScheduleNowTransformsResponseSchema = {}; + + for (const transformInfo of transformsInfo) { + const transformId = transformInfo.id; + try { + await esClient.transport.request({ + method: 'POST', + path: `_transform/${transformId}/_schedule_now`, + }); + + results[transformId] = { success: true }; + } catch (e) { + if (isRequestTimeout(e)) { + return fillResultsWithTimeouts({ + results, + id: transformId, + items: transformsInfo, + action: TRANSFORM_ACTIONS.SCHEDULE_NOW, + }); + } + results[transformId] = { success: false, error: e.meta.body.error }; + } + } + return results; +} diff --git a/x-pack/plugins/transform/server/routes/api/start_transforms/register_route.ts b/x-pack/plugins/transform/server/routes/api/start_transforms/register_route.ts new file mode 100644 index 0000000000000..5cba3a5a01d70 --- /dev/null +++ b/x-pack/plugins/transform/server/routes/api/start_transforms/register_route.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. + */ + +import { + startTransformsRequestSchema, + type StartTransformsRequestSchema, +} from '../../../../common/api_schemas/start_transforms'; +import { addInternalBasePath } from '../../../../common/constants'; + +import type { RouteDependencies } from '../../../types'; + +import { routeHandler } from './route_handler'; + +export function registerRoute({ router, license }: RouteDependencies) { + /** + * @apiGroup Transforms + * + * @api {post} /internal/transform/start_transforms Start transforms + * @apiName PostStartTransforms + * @apiDescription Starts transform + * + * @apiSchema (body) startTransformsRequestSchema + */ + router.versioned + .post({ + path: addInternalBasePath('start_transforms'), + access: 'internal', + }) + .addVersion( + { + version: '1', + validate: { + request: { + body: startTransformsRequestSchema, + }, + }, + }, + license.guardApiRoute(routeHandler) + ); +} diff --git a/x-pack/plugins/transform/server/routes/api/start_transforms/route_handler.ts b/x-pack/plugins/transform/server/routes/api/start_transforms/route_handler.ts new file mode 100644 index 0000000000000..50bbf395a5ac7 --- /dev/null +++ b/x-pack/plugins/transform/server/routes/api/start_transforms/route_handler.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 { RequestHandler } from '@kbn/core/server'; + +import type { StartTransformsRequestSchema } from '../../../../common/api_schemas/start_transforms'; + +import type { TransformRequestHandlerContext } from '../../../services/license'; + +import { wrapError, wrapEsError } from '../../utils/error_utils'; + +import { startTransforms } from './start_transforms'; + +export const routeHandler: RequestHandler< + undefined, + undefined, + StartTransformsRequestSchema, + TransformRequestHandlerContext +> = async (ctx, req, res) => { + const transformsInfo = req.body; + + try { + const esClient = (await ctx.core).elasticsearch.client; + const body = await startTransforms(transformsInfo, esClient.asCurrentUser); + return res.ok({ + body, + }); + } catch (e) { + return res.customError(wrapError(wrapEsError(e))); + } +}; diff --git a/x-pack/plugins/transform/server/routes/api/start_transforms/start_transforms.ts b/x-pack/plugins/transform/server/routes/api/start_transforms/start_transforms.ts new file mode 100644 index 0000000000000..d8097001df9bb --- /dev/null +++ b/x-pack/plugins/transform/server/routes/api/start_transforms/start_transforms.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. + */ + +import type { ElasticsearchClient } from '@kbn/core/server'; + +import { TRANSFORM_ACTIONS } from '../../../../common/types/transform'; +import type { + StartTransformsRequestSchema, + StartTransformsResponseSchema, +} from '../../../../common/api_schemas/start_transforms'; + +import { isRequestTimeout, fillResultsWithTimeouts } from '../../utils/error_utils'; + +export async function startTransforms( + transformsInfo: StartTransformsRequestSchema, + esClient: ElasticsearchClient +) { + const results: StartTransformsResponseSchema = {}; + + for (const transformInfo of transformsInfo) { + const transformId = transformInfo.id; + try { + await esClient.transform.startTransform({ + transform_id: transformId, + }); + results[transformId] = { success: true }; + } catch (e) { + if (isRequestTimeout(e)) { + return fillResultsWithTimeouts({ + results, + id: transformId, + items: transformsInfo, + action: TRANSFORM_ACTIONS.START, + }); + } + results[transformId] = { success: false, error: e.meta.body.error }; + } + } + return results; +} diff --git a/x-pack/plugins/transform/server/routes/api/stop_transforms/register_route.ts b/x-pack/plugins/transform/server/routes/api/stop_transforms/register_route.ts new file mode 100644 index 0000000000000..df9498f9ae033 --- /dev/null +++ b/x-pack/plugins/transform/server/routes/api/stop_transforms/register_route.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. + */ + +import { + stopTransformsRequestSchema, + type StopTransformsRequestSchema, +} from '../../../../common/api_schemas/stop_transforms'; +import { addInternalBasePath } from '../../../../common/constants'; + +import type { RouteDependencies } from '../../../types'; + +import { routeHandler } from './route_handler'; + +export function registerRoute({ router, license }: RouteDependencies) { + /** + * @apiGroup Transforms + * + * @api {post} /internal/transform/stop_transforms Stop transforms + * @apiName PostStopTransforms + * @apiDescription Stops transform + * + * @apiSchema (body) stopTransformsRequestSchema + */ + router.versioned + .post({ + path: addInternalBasePath('stop_transforms'), + access: 'internal', + }) + .addVersion( + { + version: '1', + validate: { + request: { + body: stopTransformsRequestSchema, + }, + }, + }, + license.guardApiRoute(routeHandler) + ); +} diff --git a/x-pack/plugins/transform/server/routes/api/stop_transforms/route_handler.ts b/x-pack/plugins/transform/server/routes/api/stop_transforms/route_handler.ts new file mode 100644 index 0000000000000..3ad753ec24c55 --- /dev/null +++ b/x-pack/plugins/transform/server/routes/api/stop_transforms/route_handler.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 type { RequestHandler } from '@kbn/core/server'; + +import type { StopTransformsRequestSchema } from '../../../../common/api_schemas/stop_transforms'; + +import type { TransformRequestHandlerContext } from '../../../services/license'; + +import { wrapError, wrapEsError } from '../../utils/error_utils'; + +import { stopTransforms } from './stop_transforms'; + +export const routeHandler: RequestHandler< + undefined, + undefined, + StopTransformsRequestSchema, + TransformRequestHandlerContext +> = async (ctx, req, res) => { + const transformsInfo = req.body; + + try { + const esClient = (await ctx.core).elasticsearch.client; + return res.ok({ + body: await stopTransforms(transformsInfo, esClient.asCurrentUser), + }); + } catch (e) { + return res.customError(wrapError(wrapEsError(e))); + } +}; diff --git a/x-pack/plugins/transform/server/routes/api/stop_transforms/stop_transforms.ts b/x-pack/plugins/transform/server/routes/api/stop_transforms/stop_transforms.ts new file mode 100644 index 0000000000000..2096c9f9f0ca5 --- /dev/null +++ b/x-pack/plugins/transform/server/routes/api/stop_transforms/stop_transforms.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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type { ElasticsearchClient } from '@kbn/core/server'; + +import { TRANSFORM_ACTIONS } from '../../../../common/types/transform'; +import { TRANSFORM_STATE } from '../../../../common/constants'; +import type { + StopTransformsRequestSchema, + StopTransformsResponseSchema, +} from '../../../../common/api_schemas/stop_transforms'; + +import { isRequestTimeout, fillResultsWithTimeouts } from '../../utils/error_utils'; + +export async function stopTransforms( + transformsInfo: StopTransformsRequestSchema, + esClient: ElasticsearchClient +) { + const results: StopTransformsResponseSchema = {}; + + for (const transformInfo of transformsInfo) { + const transformId = transformInfo.id; + try { + await esClient.transform.stopTransform({ + transform_id: transformId, + force: + transformInfo.state !== undefined + ? transformInfo.state === TRANSFORM_STATE.FAILED + : false, + wait_for_completion: true, + }); + results[transformId] = { success: true }; + } catch (e) { + if (isRequestTimeout(e)) { + return fillResultsWithTimeouts({ + results, + id: transformId, + items: transformsInfo, + action: TRANSFORM_ACTIONS.STOP, + }); + } + results[transformId] = { success: false, error: e.meta.body.error }; + } + } + return results; +} diff --git a/x-pack/plugins/transform/server/routes/api/transforms.ts b/x-pack/plugins/transform/server/routes/api/transforms.ts deleted file mode 100644 index 80d44c0e907bf..0000000000000 --- a/x-pack/plugins/transform/server/routes/api/transforms.ts +++ /dev/null @@ -1,1021 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; - -import { - ElasticsearchClient, - KibanaResponseFactory, - RequestHandler, - RequestHandlerContext, -} from '@kbn/core/server'; - -import { DataViewsService } from '@kbn/data-views-plugin/common'; -import type { TransportRequestOptions } from '@elastic/elasticsearch'; -import { generateTransformSecondaryAuthHeaders } from '../../../common/utils/transform_api_key'; -import { - reauthorizeTransformsRequestSchema, - ReauthorizeTransformsRequestSchema, - ReauthorizeTransformsResponseSchema, -} from '../../../common/api_schemas/reauthorize_transforms'; -import { addInternalBasePath, TRANSFORM_STATE } from '../../../common/constants'; -import { - transformIdParamSchema, - ResponseStatus, - TransformIdParamSchema, -} from '../../../common/api_schemas/common'; -import { - deleteTransformsRequestSchema, - DeleteTransformsRequestSchema, - DeleteTransformsResponseSchema, -} from '../../../common/api_schemas/delete_transforms'; -import { - resetTransformsRequestSchema, - ResetTransformsRequestSchema, - ResetTransformsResponseSchema, -} from '../../../common/api_schemas/reset_transforms'; -import { - startTransformsRequestSchema, - StartTransformsRequestSchema, - StartTransformsResponseSchema, -} from '../../../common/api_schemas/start_transforms'; -import { - stopTransformsRequestSchema, - StopTransformsRequestSchema, - StopTransformsResponseSchema, -} from '../../../common/api_schemas/stop_transforms'; -import { - scheduleNowTransformsRequestSchema, - ScheduleNowTransformsRequestSchema, - ScheduleNowTransformsResponseSchema, -} from '../../../common/api_schemas/schedule_now_transforms'; -import { - postTransformsUpdateRequestSchema, - PostTransformsUpdateRequestSchema, -} from '../../../common/api_schemas/update_transforms'; -import { - postTransformsPreviewRequestSchema, - PostTransformsPreviewRequestSchema, - putTransformsRequestSchema, - PutTransformsRequestSchema, - PutTransformsResponseSchema, -} from '../../../common/api_schemas/transforms'; - -import { RouteDependencies } from '../../types'; - -import { isRequestTimeout, fillResultsWithTimeouts, wrapError, wrapEsError } from './error_utils'; -import { registerTransformsAuditMessagesRoutes } from './transforms_audit_messages'; -import { registerTransformNodesRoutes } from './transforms_nodes'; -import { isLatestTransform } from '../../../common/types/transform'; -import { isKeywordDuplicate } from '../../../common/utils/field_utils'; -import { transformHealthServiceProvider } from '../../lib/alerting/transform_health_rule_type/transform_health_service'; - -enum TRANSFORM_ACTIONS { - DELETE = 'delete', - REAUTHORIZE = 'reauthorize', - RESET = 'reset', - SCHEDULE_NOW = 'schedule_now', - STOP = 'stop', - START = 'start', -} - -export function registerTransformsRoutes(routeDependencies: RouteDependencies) { - const { router, license, coreStart, dataViews, security: securityStart } = routeDependencies; - /** - * @apiGroup Transforms - * - * @api {get} /internal/transform/transforms Get transforms - * @apiName GetTransforms - * @apiDescription Returns transforms - * - * @apiSchema (params) jobAuditMessagesJobIdSchema - * @apiSchema (query) jobAuditMessagesQuerySchema - */ - router.versioned - .get({ - path: addInternalBasePath('transforms'), - access: 'internal', - }) - .addVersion( - { - version: '1', - validate: false, - }, - license.guardApiRoute( - async (ctx, req, res) => { - try { - const esClient = (await ctx.core).elasticsearch.client; - const body = await esClient.asCurrentUser.transform.getTransform({ - size: 1000, - ...req.params, - }); - - const alerting = await ctx.alerting; - if (alerting) { - const transformHealthService = transformHealthServiceProvider({ - esClient: esClient.asCurrentUser, - rulesClient: alerting.getRulesClient(), - }); - - // @ts-ignore - await transformHealthService.populateTransformsWithAssignedRules(body.transforms); - } - - return res.ok({ body }); - } catch (e) { - return res.customError(wrapError(wrapEsError(e))); - } - } - ) - ); - - /** - * @apiGroup Transforms - * - * @api {get} /internal/transform/transforms/:transformId Get transform - * @apiName GetTransform - * @apiDescription Returns a single transform - * - * @apiSchema (params) transformIdParamSchema - */ - router.versioned - .get({ - path: addInternalBasePath('transforms/{transformId}'), - access: 'internal', - }) - .addVersion( - { - version: '1', - validate: { - request: { - params: transformIdParamSchema, - }, - }, - }, - license.guardApiRoute(async (ctx, req, res) => { - const { transformId } = req.params; - try { - const esClient = (await ctx.core).elasticsearch.client; - const body = await esClient.asCurrentUser.transform.getTransform({ - transform_id: transformId, - }); - return res.ok({ body }); - } catch (e) { - return res.customError(wrapError(wrapEsError(e))); - } - }) - ); - - /** - * @apiGroup Transforms - * - * @api {get} /internal/transform/transforms/_stats Get transforms stats - * @apiName GetTransformsStats - * @apiDescription Returns transforms stats - */ - router.versioned - .get({ - path: addInternalBasePath('transforms/_stats'), - access: 'internal', - }) - .addVersion( - { - version: '1', - validate: false, - }, - license.guardApiRoute( - async (ctx, req, res) => { - try { - const esClient = (await ctx.core).elasticsearch.client; - const body = await esClient.asCurrentUser.transform.getTransformStats( - { - size: 1000, - transform_id: '_all', - }, - { maxRetries: 0 } - ); - return res.ok({ body }); - } catch (e) { - return res.customError(wrapError(wrapEsError(e))); - } - } - ) - ); - - /** - * @apiGroup Transforms - * - * @api {get} /internal/transform/transforms/:transformId/_stats Get transform stats - * @apiName GetTransformStats - * @apiDescription Returns stats for a single transform - * - * @apiSchema (params) transformIdParamSchema - */ - router.versioned - .get({ - path: addInternalBasePath('transforms/{transformId}/_stats'), - access: 'internal', - }) - .addVersion( - { - version: '1', - validate: { - request: { - params: transformIdParamSchema, - }, - }, - }, - license.guardApiRoute(async (ctx, req, res) => { - const { transformId } = req.params; - try { - const esClient = (await ctx.core).elasticsearch.client; - const body = await esClient.asCurrentUser.transform.getTransformStats( - { - transform_id: transformId, - }, - { maxRetries: 0 } - ); - return res.ok({ body }); - } catch (e) { - return res.customError(wrapError(wrapEsError(e))); - } - }) - ); - - /** - * @apiGroup Transforms - * - * @api {put} /internal/transform/transforms/:transformId Put transform - * @apiName PutTransform - * @apiDescription Creates a transform - * - * @apiSchema (params) transformIdParamSchema - * @apiSchema (body) putTransformsRequestSchema - */ - router.versioned - .put({ - path: addInternalBasePath('transforms/{transformId}'), - access: 'internal', - }) - .addVersion( - { - version: '1', - validate: { - request: { - params: transformIdParamSchema, - body: putTransformsRequestSchema, - }, - }, - }, - license.guardApiRoute( - async (ctx, req, res) => { - const { transformId } = req.params; - - const response: PutTransformsResponseSchema = { - transformsCreated: [], - errors: [], - }; - - const esClient = (await ctx.core).elasticsearch.client; - await esClient.asCurrentUser.transform - .putTransform({ - // @ts-expect-error @elastic/elasticsearch group_by is expected to be optional in TransformPivot - body: req.body, - transform_id: transformId, - }) - .then(() => { - response.transformsCreated.push({ transform: transformId }); - }) - .catch((e) => - response.errors.push({ - id: transformId, - error: wrapEsError(e), - }) - ); - - return res.ok({ body: response }); - } - ) - ); - - /** - * @apiGroup Transforms - * - * @api {post} /internal/transform/transforms/:transformId/_update Post transform update - * @apiName PostTransformUpdate - * @apiDescription Updates a transform - * - * @apiSchema (params) transformIdParamSchema - * @apiSchema (body) postTransformsUpdateRequestSchema - */ - router.versioned - .post({ - path: addInternalBasePath('transforms/{transformId}/_update'), - access: 'internal', - }) - .addVersion( - { - version: '1', - validate: { - request: { - params: transformIdParamSchema, - body: postTransformsUpdateRequestSchema, - }, - }, - }, - license.guardApiRoute( - async (ctx, req, res) => { - const { transformId } = req.params; - - try { - const esClient = (await ctx.core).elasticsearch.client; - const body = await esClient.asCurrentUser.transform.updateTransform({ - // @ts-expect-error query doesn't satisfy QueryDslQueryContainer from @elastic/elasticsearch - body: req.body, - transform_id: transformId, - }); - return res.ok({ - body, - }); - } catch (e) { - return res.customError(wrapError(e)); - } - } - ) - ); - - /** - * @apiGroup Reauthorize transforms with API key generated from currently logged in user - * @api {post} /internal/transform/reauthorize_transforms Post reauthorize transforms - * @apiName Reauthorize Transforms - * @apiDescription Reauthorize transforms by generating an API Key for current user - * and update transform's es-secondary-authorization headers with the generated key, - * then start the transform. - * @apiSchema (body) reauthorizeTransformsRequestSchema - */ - router.versioned - .post({ - path: addInternalBasePath('reauthorize_transforms'), - access: 'internal', - }) - .addVersion( - { - version: '1', - validate: { - request: { - body: reauthorizeTransformsRequestSchema, - }, - }, - }, - license.guardApiRoute( - async (ctx, req, res) => { - try { - const transformsInfo = req.body; - const { elasticsearch } = coreStart; - const esClient = elasticsearch.client.asScoped(req).asCurrentUser; - - let apiKeyWithCurrentUserPermission; - - // If security is not enabled or available, user should not have the need to reauthorize - // in that case, start anyway - if (securityStart) { - apiKeyWithCurrentUserPermission = - await securityStart.authc.apiKeys.grantAsInternalUser(req, { - name: `auto-generated-transform-api-key`, - role_descriptors: {}, - }); - } - const secondaryAuth = generateTransformSecondaryAuthHeaders( - apiKeyWithCurrentUserPermission - ); - - const authorizedTransforms = await reauthorizeAndStartTransforms( - transformsInfo, - esClient, - { - ...(secondaryAuth ? secondaryAuth : {}), - } - ); - return res.ok({ body: authorizedTransforms }); - } catch (e) { - return res.customError(wrapError(wrapEsError(e))); - } - } - ) - ); - - /** - * @apiGroup Transforms - * - * @api {post} /internal/transform/delete_transforms Post delete transforms - * @apiName DeleteTransforms - * @apiDescription Deletes transforms - * - * @apiSchema (body) deleteTransformsRequestSchema - */ - router.versioned - .post({ - path: addInternalBasePath('delete_transforms'), - access: 'internal', - }) - .addVersion( - { - version: '1', - validate: { - request: { - body: deleteTransformsRequestSchema, - }, - }, - }, - license.guardApiRoute( - async (ctx, req, res) => { - try { - const { savedObjects, elasticsearch } = coreStart; - const savedObjectsClient = savedObjects.getScopedClient(req); - const esClient = elasticsearch.client.asScoped(req).asCurrentUser; - - const dataViewsService = await dataViews.dataViewsServiceFactory( - savedObjectsClient, - esClient, - req - ); - const body = await deleteTransforms(req.body, ctx, res, dataViewsService); - - if (body && body.status) { - if (body.status === 404) { - return res.notFound(); - } - if (body.status === 403) { - return res.forbidden(); - } - } - - return res.ok({ - body, - }); - } catch (e) { - return res.customError(wrapError(wrapEsError(e))); - } - } - ) - ); - - /** - * @apiGroup Transforms - * - * @api {post} /internal/transform/reset_transforms Post reset transforms - * @apiName ResetTransforms - * @apiDescription resets transforms - * - * @apiSchema (body) resetTransformsRequestSchema - */ - router.versioned - .post({ - path: addInternalBasePath('reset_transforms'), - access: 'internal', - }) - .addVersion( - { - version: '1', - validate: { - request: { - body: resetTransformsRequestSchema, - }, - }, - }, - license.guardApiRoute( - async (ctx, req, res) => { - try { - const body = await resetTransforms(req.body, ctx, res); - - if (body && body.status) { - if (body.status === 404) { - return res.notFound(); - } - if (body.status === 403) { - return res.forbidden(); - } - } - - return res.ok({ - body, - }); - } catch (e) { - return res.customError(wrapError(wrapEsError(e))); - } - } - ) - ); - - /** - * @apiGroup Transforms - * - * @api {post} /internal/transform/transforms/_preview Preview transform - * @apiName PreviewTransform - * @apiDescription Previews transform - * - * @apiSchema (body) postTransformsPreviewRequestSchema - */ - router.versioned - .post({ - path: addInternalBasePath('transforms/_preview'), - access: 'internal', - }) - .addVersion( - { - version: '1', - validate: { - request: { - body: postTransformsPreviewRequestSchema, - }, - }, - }, - license.guardApiRoute( - previewTransformHandler - ) - ); - - /** - * @apiGroup Transforms - * - * @api {post} /internal/transform/start_transforms Start transforms - * @apiName PostStartTransforms - * @apiDescription Starts transform - * - * @apiSchema (body) startTransformsRequestSchema - */ - router.versioned - .post({ - path: addInternalBasePath('start_transforms'), - access: 'internal', - }) - .addVersion( - { - version: '1', - validate: { - request: { - body: startTransformsRequestSchema, - }, - }, - }, - license.guardApiRoute( - startTransformsHandler - ) - ); - - /** - * @apiGroup Transforms - * - * @api {post} /internal/transform/stop_transforms Stop transforms - * @apiName PostStopTransforms - * @apiDescription Stops transform - * - * @apiSchema (body) stopTransformsRequestSchema - */ - router.versioned - .post({ - path: addInternalBasePath('stop_transforms'), - access: 'internal', - }) - .addVersion( - { - version: '1', - validate: { - request: { - body: stopTransformsRequestSchema, - }, - }, - }, - license.guardApiRoute( - stopTransformsHandler - ) - ); - - /** - * @apiGroup Transforms - * - * @api {post} /internal/transform/schedule_now_transforms Schedules transforms now - * @apiName PostScheduleNowTransforms - * @apiDescription Schedules transforms now - * - * @apiSchema (body) scheduleNowTransformsRequestSchema - */ - router.versioned - .post({ - path: addInternalBasePath('schedule_now_transforms'), - access: 'internal', - }) - .addVersion( - { - version: '1', - validate: { - request: { - body: scheduleNowTransformsRequestSchema, - }, - }, - }, - license.guardApiRoute( - scheduleNowTransformsHandler - ) - ); - - registerTransformsAuditMessagesRoutes(routeDependencies); - registerTransformNodesRoutes(routeDependencies); -} - -async function getDataViewId(indexName: string, dataViewsService: DataViewsService) { - const dv = (await dataViewsService.find(indexName)).find(({ title }) => title === indexName); - return dv?.id; -} - -async function deleteDestDataViewById(dataViewId: string, dataViewsService: DataViewsService) { - return await dataViewsService.delete(dataViewId); -} - -async function deleteTransforms( - reqBody: DeleteTransformsRequestSchema, - ctx: RequestHandlerContext, - response: KibanaResponseFactory, - dataViewsService: DataViewsService -) { - const { transformsInfo } = reqBody; - - // Cast possible undefineds as booleans - const deleteDestIndex = !!reqBody.deleteDestIndex; - const deleteDestDataView = !!reqBody.deleteDestDataView; - const shouldForceDelete = !!reqBody.forceDelete; - - const results: DeleteTransformsResponseSchema = {}; - - const coreContext = await ctx.core; - const esClient = coreContext.elasticsearch.client; - - for (const transformInfo of transformsInfo) { - let destinationIndex: string | undefined; - - const transformDeleted: ResponseStatus = { success: false }; - const destIndexDeleted: ResponseStatus = { success: false }; - const destDataViewDeleted: ResponseStatus = { - success: false, - }; - const transformId = transformInfo.id; - // force delete only if the transform has failed - let needToForceDelete = false; - - try { - if (transformInfo.state === TRANSFORM_STATE.FAILED) { - needToForceDelete = true; - } - if (!shouldForceDelete) { - // Grab destination index info to delete - try { - const body = await esClient.asCurrentUser.transform.getTransform({ - transform_id: transformId, - }); - const transformConfig = body.transforms[0]; - destinationIndex = transformConfig.dest.index; - } catch (getTransformConfigError) { - transformDeleted.error = getTransformConfigError.meta.body.error; - results[transformId] = { - transformDeleted, - destIndexDeleted, - destDataViewDeleted, - destinationIndex, - }; - // No need to perform further delete attempts - continue; - } - } - - // Delete the data view if there's a data view that matches the name of dest index - if (destinationIndex && deleteDestDataView) { - try { - const dataViewId = await getDataViewId(destinationIndex, dataViewsService); - if (dataViewId) { - await deleteDestDataViewById(dataViewId, dataViewsService); - destDataViewDeleted.success = true; - } - } catch (deleteDestDataViewError) { - destDataViewDeleted.error = deleteDestDataViewError.meta.body.error; - } - } - - try { - await esClient.asCurrentUser.transform.deleteTransform({ - transform_id: transformId, - force: shouldForceDelete && needToForceDelete, - // @ts-expect-error ES type needs to be updated - delete_dest_index: deleteDestIndex, - }); - transformDeleted.success = true; - destIndexDeleted.success = deleteDestIndex; - } catch (deleteTransformJobError) { - transformDeleted.error = deleteTransformJobError.meta.body.error; - if (deleteTransformJobError.statusCode === 403) { - return response.forbidden(); - } - } - - results[transformId] = { - transformDeleted, - destIndexDeleted, - destDataViewDeleted, - destinationIndex, - }; - } catch (e) { - if (isRequestTimeout(e)) { - return fillResultsWithTimeouts({ - results, - id: transformInfo.id, - items: transformsInfo, - action: TRANSFORM_ACTIONS.DELETE, - }); - } - results[transformId] = { transformDeleted: { success: false, error: e.meta.body.error } }; - } - } - return results; -} - -async function resetTransforms( - reqBody: ResetTransformsRequestSchema, - ctx: RequestHandlerContext, - response: KibanaResponseFactory -) { - const { transformsInfo } = reqBody; - - const results: ResetTransformsResponseSchema = {}; - const esClient = (await ctx.core).elasticsearch.client; - - for (const transformInfo of transformsInfo) { - const transformReset: ResponseStatus = { success: false }; - const transformId = transformInfo.id; - - try { - try { - await esClient.asCurrentUser.transform.resetTransform({ - transform_id: transformId, - }); - transformReset.success = true; - } catch (resetTransformJobError) { - transformReset.error = resetTransformJobError.meta.body.error; - if (resetTransformJobError.statusCode === 403) { - return response.forbidden(); - } - } - - results[transformId] = { - transformReset, - }; - } catch (e) { - if (isRequestTimeout(e)) { - return fillResultsWithTimeouts({ - results, - id: transformInfo.id, - items: transformsInfo, - action: TRANSFORM_ACTIONS.RESET, - }); - } - results[transformId] = { transformReset: { success: false, error: e.meta.body.error } }; - } - } - return results; -} - -const previewTransformHandler: RequestHandler< - undefined, - undefined, - PostTransformsPreviewRequestSchema -> = async (ctx, req, res) => { - try { - const reqBody = req.body; - const esClient = (await ctx.core).elasticsearch.client; - const body = await esClient.asCurrentUser.transform.previewTransform( - { - body: reqBody, - }, - { maxRetries: 0 } - ); - if (isLatestTransform(reqBody)) { - // for the latest transform mappings properties have to be retrieved from the source - const fieldCapsResponse = await esClient.asCurrentUser.fieldCaps( - { - index: reqBody.source.index, - fields: '*', - include_unmapped: false, - }, - { maxRetries: 0 } - ); - - const fieldNamesSet = new Set(Object.keys(fieldCapsResponse.fields)); - - const fields = Object.entries( - fieldCapsResponse.fields as Record> - ).reduce((acc, [fieldName, fieldCaps]) => { - const fieldDefinition = Object.values(fieldCaps)[0]; - const isMetaField = fieldDefinition.type.startsWith('_') || fieldName === '_doc_count'; - if (isMetaField || isKeywordDuplicate(fieldName, fieldNamesSet)) { - return acc; - } - acc[fieldName] = { ...fieldDefinition }; - return acc; - }, {} as Record); - - body.generated_dest_index.mappings!.properties = fields as Record< - string, - estypes.MappingProperty - >; - } - return res.ok({ body }); - } catch (e) { - return res.customError(wrapError(wrapEsError(e))); - } -}; - -const startTransformsHandler: RequestHandler< - undefined, - undefined, - StartTransformsRequestSchema -> = async (ctx, req, res) => { - const transformsInfo = req.body; - - try { - const esClient = (await ctx.core).elasticsearch.client; - const body = await startTransforms(transformsInfo, esClient.asCurrentUser); - return res.ok({ - body, - }); - } catch (e) { - return res.customError(wrapError(wrapEsError(e))); - } -}; - -async function startTransforms( - transformsInfo: StartTransformsRequestSchema, - esClient: ElasticsearchClient -) { - const results: StartTransformsResponseSchema = {}; - - for (const transformInfo of transformsInfo) { - const transformId = transformInfo.id; - try { - await esClient.transform.startTransform({ - transform_id: transformId, - }); - results[transformId] = { success: true }; - } catch (e) { - if (isRequestTimeout(e)) { - return fillResultsWithTimeouts({ - results, - id: transformId, - items: transformsInfo, - action: TRANSFORM_ACTIONS.START, - }); - } - results[transformId] = { success: false, error: e.meta.body.error }; - } - } - return results; -} - -const stopTransformsHandler: RequestHandler< - undefined, - undefined, - StopTransformsRequestSchema -> = async (ctx, req, res) => { - const transformsInfo = req.body; - - try { - const esClient = (await ctx.core).elasticsearch.client; - return res.ok({ - body: await stopTransforms(transformsInfo, esClient.asCurrentUser), - }); - } catch (e) { - return res.customError(wrapError(wrapEsError(e))); - } -}; - -async function stopTransforms( - transformsInfo: StopTransformsRequestSchema, - esClient: ElasticsearchClient -) { - const results: StopTransformsResponseSchema = {}; - - for (const transformInfo of transformsInfo) { - const transformId = transformInfo.id; - try { - await esClient.transform.stopTransform({ - transform_id: transformId, - force: - transformInfo.state !== undefined - ? transformInfo.state === TRANSFORM_STATE.FAILED - : false, - wait_for_completion: true, - }); - results[transformId] = { success: true }; - } catch (e) { - if (isRequestTimeout(e)) { - return fillResultsWithTimeouts({ - results, - id: transformId, - items: transformsInfo, - action: TRANSFORM_ACTIONS.STOP, - }); - } - results[transformId] = { success: false, error: e.meta.body.error }; - } - } - return results; -} - -const scheduleNowTransformsHandler: RequestHandler< - undefined, - undefined, - ScheduleNowTransformsRequestSchema -> = async (ctx, req, res) => { - const transformsInfo = req.body; - - try { - const esClient = (await ctx.core).elasticsearch.client; - return res.ok({ - body: await scheduleNowTransforms(transformsInfo, esClient.asCurrentUser), - }); - } catch (e) { - return res.customError(wrapError(wrapEsError(e))); - } -}; - -async function scheduleNowTransforms( - transformsInfo: ScheduleNowTransformsRequestSchema, - esClient: ElasticsearchClient -) { - const results: ScheduleNowTransformsResponseSchema = {}; - - for (const transformInfo of transformsInfo) { - const transformId = transformInfo.id; - try { - await esClient.transport.request({ - method: 'POST', - path: `_transform/${transformId}/_schedule_now`, - }); - - results[transformId] = { success: true }; - } catch (e) { - if (isRequestTimeout(e)) { - return fillResultsWithTimeouts({ - results, - id: transformId, - items: transformsInfo, - action: TRANSFORM_ACTIONS.SCHEDULE_NOW, - }); - } - results[transformId] = { success: false, error: e.meta.body.error }; - } - } - return results; -} - -async function reauthorizeAndStartTransforms( - transformsInfo: ReauthorizeTransformsRequestSchema, - esClient: ElasticsearchClient, - options?: TransportRequestOptions -) { - const results: ReauthorizeTransformsResponseSchema = {}; - - for (const transformInfo of transformsInfo) { - const transformId = transformInfo.id; - try { - await esClient.transform.updateTransform( - { - body: {}, - transform_id: transformId, - }, - options ?? {} - ); - - await esClient.transform.startTransform( - { - transform_id: transformId, - }, - { ignore: [409] } - ); - - results[transformId] = { success: true }; - } catch (e) { - if (isRequestTimeout(e)) { - return fillResultsWithTimeouts({ - results, - id: transformId, - items: transformsInfo, - action: TRANSFORM_ACTIONS.REAUTHORIZE, - }); - } - results[transformId] = { success: false, error: e.meta.body.error }; - } - } - return results; -} diff --git a/x-pack/plugins/transform/server/routes/api/transforms_all/register_route.ts b/x-pack/plugins/transform/server/routes/api/transforms_all/register_route.ts new file mode 100644 index 0000000000000..e808e0e8fafc2 --- /dev/null +++ b/x-pack/plugins/transform/server/routes/api/transforms_all/register_route.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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; + +import { addInternalBasePath } from '../../../../common/constants'; + +import type { RouteDependencies } from '../../../types'; + +import { routeHandler } from './route_handler'; + +export function registerRoute({ router, license }: RouteDependencies) { + /** + * @apiGroup Transforms + * + * @api {get} /internal/transform/transforms Get transforms + * @apiName GetTransforms + * @apiDescription Returns transforms + * + * @apiSchema (params) jobAuditMessagesJobIdSchema + * @apiSchema (query) jobAuditMessagesQuerySchema + */ + router.versioned + .get({ + path: addInternalBasePath('transforms'), + access: 'internal', + }) + .addVersion( + { + version: '1', + validate: false, + }, + license.guardApiRoute( + routeHandler + ) + ); +} diff --git a/x-pack/plugins/transform/server/routes/api/transforms_all/route_handler.ts b/x-pack/plugins/transform/server/routes/api/transforms_all/route_handler.ts new file mode 100644 index 0000000000000..10d52b86f8df8 --- /dev/null +++ b/x-pack/plugins/transform/server/routes/api/transforms_all/route_handler.ts @@ -0,0 +1,45 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; + +import type { RequestHandler } from '@kbn/core/server'; + +import { TransformRequestHandlerContext } from '../../../services/license'; +import { transformHealthServiceProvider } from '../../../lib/alerting/transform_health_rule_type/transform_health_service'; + +import { wrapError, wrapEsError } from '../../utils/error_utils'; + +export const routeHandler: RequestHandler< + estypes.TransformGetTransformRequest, + undefined, + undefined, + TransformRequestHandlerContext +> = async (ctx, req, res) => { + try { + const esClient = (await ctx.core).elasticsearch.client; + const body = await esClient.asCurrentUser.transform.getTransform({ + size: 1000, + ...req.params, + }); + + const alerting = await ctx.alerting; + if (alerting) { + const transformHealthService = transformHealthServiceProvider({ + esClient: esClient.asCurrentUser, + rulesClient: alerting.getRulesClient(), + }); + + // @ts-ignore + await transformHealthService.populateTransformsWithAssignedRules(body.transforms); + } + + return res.ok({ body }); + } catch (e) { + return res.customError(wrapError(wrapEsError(e))); + } +}; diff --git a/x-pack/plugins/transform/server/routes/api/transforms_audit_messages.ts b/x-pack/plugins/transform/server/routes/api/transforms_audit_messages.ts deleted file mode 100644 index 5aeecf399bbd3..0000000000000 --- a/x-pack/plugins/transform/server/routes/api/transforms_audit_messages.ts +++ /dev/null @@ -1,133 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { schema } from '@kbn/config-schema'; -import { addInternalBasePath, DEFAULT_MAX_AUDIT_MESSAGE_SIZE } from '../../../common/constants'; -import { transformIdParamSchema, TransformIdParamSchema } from '../../../common/api_schemas/common'; -import { AuditMessage } from '../../../common/types/messages'; - -import { RouteDependencies } from '../../types'; - -import { wrapError, wrapEsError } from './error_utils'; - -export const ML_DF_NOTIFICATION_INDEX_PATTERN = '.transform-notifications-read'; - -interface BoolQuery { - bool: { [key: string]: any }; -} - -interface TransformMessageQuery { - sortField: string; - sortDirection: 'asc' | 'desc'; -} - -export function registerTransformsAuditMessagesRoutes({ router, license }: RouteDependencies) { - /** - * @apiGroup Transforms Audit Messages - * - * @api {get} /internal/transform/transforms/:transformId/messages Transforms Messages - * @apiName GetTransformsMessages - * @apiDescription Get transforms audit messages - * - * @apiSchema (params) transformIdParamSchema - */ - router.versioned - .get({ - path: addInternalBasePath('transforms/{transformId}/messages'), - access: 'internal', - }) - .addVersion( - { - version: '1', - validate: { - request: { - params: transformIdParamSchema, - query: schema.object({ - sortField: schema.string(), - sortDirection: schema.oneOf([schema.literal('asc'), schema.literal('desc')]), - }), - }, - }, - }, - license.guardApiRoute( - async (ctx, req, res) => { - const { transformId } = req.params; - const sortField = req.query?.sortField ?? 'timestamp'; - const sortDirection = req.query?.sortDirection ?? 'desc'; - - // search for audit messages, - // transformId is optional. without it, all transforms will be listed. - const query: BoolQuery = { - bool: { - filter: [ - { - bool: { - must_not: { - term: { - level: 'activity', - }, - }, - }, - }, - ], - }, - }; - - // if no transformId specified, load all of the messages - if (transformId !== undefined) { - query.bool.filter.push({ - bool: { - should: [ - { - term: { - transform_id: '', // catch system messages - }, - }, - { - term: { - transform_id: transformId, // messages for specified transformId - }, - }, - ], - }, - }); - } - - try { - const esClient = (await ctx.core).elasticsearch.client; - const resp = await esClient.asCurrentUser.search({ - index: ML_DF_NOTIFICATION_INDEX_PATTERN, - ignore_unavailable: true, - size: DEFAULT_MAX_AUDIT_MESSAGE_SIZE, - body: { - sort: [ - { [sortField]: { order: sortDirection } }, - { transform_id: { order: 'asc' as const } }, - ], - query, - }, - track_total_hits: true, - }); - const totalHits = - typeof resp.hits.total === 'number' ? resp.hits.total : resp.hits.total!.value; - - let messages: AuditMessage[] = []; - // TODO: remove typeof checks when appropriate overloading is added for the `search` API - if ( - (typeof resp.hits.total === 'number' && resp.hits.total > 0) || - (typeof resp.hits.total === 'object' && resp.hits.total.value > 0) - ) { - messages = resp.hits.hits.map((hit) => hit._source!); - } - return res.ok({ body: { messages, total: totalHits } }); - } catch (e) { - return res.customError(wrapError(wrapEsError(e))); - } - } - ) - ); -} diff --git a/x-pack/plugins/transform/server/routes/api/transforms_create/register_route.ts b/x-pack/plugins/transform/server/routes/api/transforms_create/register_route.ts new file mode 100644 index 0000000000000..49b8e7c138357 --- /dev/null +++ b/x-pack/plugins/transform/server/routes/api/transforms_create/register_route.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 { + transformIdParamSchema, + type TransformIdParamSchema, +} from '../../../../common/api_schemas/common'; +import { + putTransformsRequestSchema, + putTransformsQuerySchema, + type PutTransformsRequestSchema, + type PutTransformsQuerySchema, +} from '../../../../common/api_schemas/transforms'; +import { addInternalBasePath } from '../../../../common/constants'; + +import type { RouteDependencies } from '../../../types'; + +import { routeHandlerFactory } from './route_handler_factory'; + +export function registerRoute(routeDependencies: RouteDependencies) { + const { router, license } = routeDependencies; + + /** + * @apiGroup Transforms + * + * @api {put} /internal/transform/transforms/:transformId Put transform + * @apiName PutTransform + * @apiDescription Creates a transform + * + * @apiSchema (params) transformIdParamSchema + * @apiSchema (query) transformIdParamSchema + * @apiSchema (body) putTransformsRequestSchema + */ + router.versioned + .put({ + path: addInternalBasePath('transforms/{transformId}'), + access: 'internal', + }) + .addVersion( + { + version: '1', + validate: { + request: { + params: transformIdParamSchema, + query: putTransformsQuerySchema, + body: putTransformsRequestSchema, + }, + }, + }, + license.guardApiRoute< + TransformIdParamSchema, + PutTransformsQuerySchema, + PutTransformsRequestSchema + >(routeHandlerFactory(routeDependencies)) + ); +} diff --git a/x-pack/plugins/transform/server/routes/api/transforms_create/route_handler_factory.ts b/x-pack/plugins/transform/server/routes/api/transforms_create/route_handler_factory.ts new file mode 100644 index 0000000000000..1679bbf3a6309 --- /dev/null +++ b/x-pack/plugins/transform/server/routes/api/transforms_create/route_handler_factory.ts @@ -0,0 +1,108 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license 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 { RequestHandler } from '@kbn/core/server'; +import type { RuntimeField } from '@kbn/data-views-plugin/common'; +import { isPopulatedObject } from '@kbn/ml-is-populated-object'; + +import type { TransformIdParamSchema } from '../../../../common/api_schemas/common'; +import type { + PutTransformsRequestSchema, + PutTransformsQuerySchema, + PutTransformsResponseSchema, +} from '../../../../common/api_schemas/transforms'; +import { isLatestTransform } from '../../../../common/types/transform'; + +import type { RouteDependencies } from '../../../types'; +import type { TransformRequestHandlerContext } from '../../../services/license'; + +import { wrapEsError } from '../../utils/error_utils'; + +export const routeHandlerFactory: ( + routeDependencies: RouteDependencies +) => RequestHandler< + TransformIdParamSchema, + PutTransformsQuerySchema, + PutTransformsRequestSchema, + TransformRequestHandlerContext +> = (routeDependencies) => async (ctx, req, res) => { + const { coreStart, dataViews } = routeDependencies; + const { transformId } = req.params; + const { createDataView, timeFieldName } = req.query; + + const response: PutTransformsResponseSchema = { + dataViewsCreated: [], + dataViewsErrors: [], + transformsCreated: [], + errors: [], + }; + + const esClient = (await ctx.core).elasticsearch.client; + + try { + const resp = await esClient.asCurrentUser.transform.putTransform({ + // @ts-expect-error @elastic/elasticsearch group_by is expected to be optional in TransformPivot + body: req.body, + transform_id: transformId, + }); + + if (resp.acknowledged) { + response.transformsCreated.push({ transform: transformId }); + } else { + response.errors.push({ + id: transformId, + error: wrapEsError(resp), + }); + } + } catch (e) { + response.errors.push({ + id: transformId, + error: wrapEsError(e), + }); + } + + if (createDataView) { + const { savedObjects, elasticsearch } = coreStart; + const dataViewsService = await dataViews.dataViewsServiceFactory( + savedObjects.getScopedClient(req), + elasticsearch.client.asScoped(req).asCurrentUser, + req + ); + + const dataViewName = req.body.dest.index; + const runtimeMappings = req.body.source.runtime_mappings as Record; + + try { + const dataViewsResp = await dataViewsService.createAndSave( + { + title: dataViewName, + timeFieldName, + // Adding runtime mappings for transforms of type latest only here + // since only they will want to replicate the source index mapping. + // Pivot type transforms have index mappings that cannot be + // inferred from the source index. + ...(isPopulatedObject(runtimeMappings) && isLatestTransform(req.body) + ? { runtimeFieldMap: runtimeMappings } + : {}), + allowNoIndex: true, + }, + false, + true + ); + + if (dataViewsResp.id) { + response.dataViewsCreated = [{ id: dataViewsResp.id }]; + } + } catch (error) { + // For the error id we use the transform id + // because in case of an error we don't get a data view id. + response.dataViewsErrors = [{ id: transformId, error }]; + } + } + + return res.ok({ body: response }); +}; diff --git a/x-pack/plugins/transform/server/routes/api/transforms_nodes.ts b/x-pack/plugins/transform/server/routes/api/transforms_nodes.ts deleted file mode 100644 index 5f9b51d0fa433..0000000000000 --- a/x-pack/plugins/transform/server/routes/api/transforms_nodes.ts +++ /dev/null @@ -1,90 +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 Boom from '@hapi/boom'; - -import { isPopulatedObject } from '@kbn/ml-is-populated-object'; - -import { addInternalBasePath, NODES_INFO_PRIVILEGES } from '../../../common/constants'; - -import { RouteDependencies } from '../../types'; - -import { wrapError, wrapEsError } from './error_utils'; - -const NODE_ROLES = 'roles'; - -interface NodesAttributes { - roles: string[]; -} - -type Nodes = Record; - -export const isNodes = (arg: unknown): arg is Nodes => { - return ( - isPopulatedObject(arg) && - Object.values(arg).every( - (node) => isPopulatedObject(node, [NODE_ROLES]) && Array.isArray(node.roles) - ) - ); -}; - -export function registerTransformNodesRoutes({ router, license }: RouteDependencies) { - /** - * @apiGroup Transform Nodes - * - * @api {get} /internal/transforms/_nodes Transform Nodes - * @apiName GetTransformNodes - * @apiDescription Get transform nodes - */ - router.versioned - .get({ - path: addInternalBasePath('transforms/_nodes'), - access: 'internal', - }) - .addVersion( - { - version: '1', - validate: false, - }, - license.guardApiRoute(async (ctx, req, res) => { - try { - const esClient = (await ctx.core).elasticsearch.client; - // If security is enabled, check that the user has at least permission to - // view transforms before calling the _nodes endpoint with the internal user. - if (license.getStatus().isSecurityEnabled === true) { - const { has_all_requested: hasAllPrivileges } = - await esClient.asCurrentUser.security.hasPrivileges({ - body: { - cluster: NODES_INFO_PRIVILEGES, - }, - }); - - if (!hasAllPrivileges) { - return res.customError(wrapError(new Boom.Boom('Forbidden', { statusCode: 403 }))); - } - } - - const { nodes } = await esClient.asInternalUser.nodes.info({ - filter_path: `nodes.*.${NODE_ROLES}`, - }); - - let count = 0; - if (isNodes(nodes)) { - for (const { roles } of Object.values(nodes)) { - if (roles.includes('transform')) { - count++; - } - } - } - - return res.ok({ body: { count } }); - } catch (e) { - return res.customError(wrapError(wrapEsError(e))); - } - }) - ); -} diff --git a/x-pack/plugins/transform/server/routes/api/transforms_nodes/register_route.ts b/x-pack/plugins/transform/server/routes/api/transforms_nodes/register_route.ts new file mode 100644 index 0000000000000..ba22d01dfa016 --- /dev/null +++ b/x-pack/plugins/transform/server/routes/api/transforms_nodes/register_route.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 { addInternalBasePath } from '../../../../common/constants'; + +import { RouteDependencies } from '../../../types'; + +import { routeHandlerFactory } from './route_handler_factory'; + +export function registerRoute({ router, license }: RouteDependencies) { + /** + * @apiGroup Transform Nodes + * + * @api {get} /internal/transforms/_nodes Transform Nodes + * @apiName GetTransformNodes + * @apiDescription Get transform nodes + */ + router.versioned + .get({ + path: addInternalBasePath('transforms/_nodes'), + access: 'internal', + }) + .addVersion( + { + version: '1', + validate: false, + }, + license.guardApiRoute(routeHandlerFactory(license)) + ); +} diff --git a/x-pack/plugins/transform/server/routes/api/transforms_nodes.test.ts b/x-pack/plugins/transform/server/routes/api/transforms_nodes/route_handler_factory.test.ts similarity index 96% rename from x-pack/plugins/transform/server/routes/api/transforms_nodes.test.ts rename to x-pack/plugins/transform/server/routes/api/transforms_nodes/route_handler_factory.test.ts index 462a4688ad455..00664a0326f14 100644 --- a/x-pack/plugins/transform/server/routes/api/transforms_nodes.test.ts +++ b/x-pack/plugins/transform/server/routes/api/transforms_nodes/route_handler_factory.test.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { isNodes } from './transforms_nodes'; +import { isNodes } from './route_handler_factory'; describe('Transform: Nodes API endpoint', () => { test('isNodes()', () => { diff --git a/x-pack/plugins/transform/server/routes/api/transforms_nodes/route_handler_factory.ts b/x-pack/plugins/transform/server/routes/api/transforms_nodes/route_handler_factory.ts new file mode 100644 index 0000000000000..8eed2ad119d38 --- /dev/null +++ b/x-pack/plugins/transform/server/routes/api/transforms_nodes/route_handler_factory.ts @@ -0,0 +1,72 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import Boom from '@hapi/boom'; +import type { RequestHandler } from '@kbn/core/server'; +import { isPopulatedObject } from '@kbn/ml-is-populated-object'; + +import { NODES_INFO_PRIVILEGES } from '../../../../common/constants'; + +import { RouteDependencies } from '../../../types'; + +import { wrapError, wrapEsError } from '../../utils/error_utils'; + +const NODE_ROLES = 'roles'; + +interface NodesAttributes { + roles: string[]; +} + +type Nodes = Record; + +export const isNodes = (arg: unknown): arg is Nodes => { + return ( + isPopulatedObject(arg) && + Object.values(arg).every( + (node) => isPopulatedObject(node, [NODE_ROLES]) && Array.isArray(node.roles) + ) + ); +}; + +export const routeHandlerFactory: ( + license: RouteDependencies['license'] +) => RequestHandler = (license) => async (ctx, req, res) => { + try { + const esClient = (await ctx.core).elasticsearch.client; + // If security is enabled, check that the user has at least permission to + // view transforms before calling the _nodes endpoint with the internal user. + if (license.getStatus().isSecurityEnabled === true) { + const { has_all_requested: hasAllPrivileges } = + await esClient.asCurrentUser.security.hasPrivileges({ + body: { + cluster: NODES_INFO_PRIVILEGES, + }, + }); + + if (!hasAllPrivileges) { + return res.customError(wrapError(new Boom.Boom('Forbidden', { statusCode: 403 }))); + } + } + + const { nodes } = await esClient.asInternalUser.nodes.info({ + filter_path: `nodes.*.${NODE_ROLES}`, + }); + + let count = 0; + if (isNodes(nodes)) { + for (const { roles } of Object.values(nodes)) { + if (roles.includes('transform')) { + count++; + } + } + } + + return res.ok({ body: { count } }); + } catch (e) { + return res.customError(wrapError(wrapEsError(e))); + } +}; diff --git a/x-pack/plugins/transform/server/routes/api/transforms_preview/register_route.ts b/x-pack/plugins/transform/server/routes/api/transforms_preview/register_route.ts new file mode 100644 index 0000000000000..1b22eae72ef14 --- /dev/null +++ b/x-pack/plugins/transform/server/routes/api/transforms_preview/register_route.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. + */ + +import { + postTransformsPreviewRequestSchema, + PostTransformsPreviewRequestSchema, +} from '../../../../common/api_schemas/transforms'; +import { addInternalBasePath } from '../../../../common/constants'; + +import type { RouteDependencies } from '../../../types'; + +import { routeHandler } from './route_handler'; + +export function registerRoute({ router, license }: RouteDependencies) { + /** + * @apiGroup Transforms + * + * @api {post} /internal/transform/transforms/_preview Preview transform + * @apiName PreviewTransform + * @apiDescription Previews transform + * + * @apiSchema (body) postTransformsPreviewRequestSchema + */ + router.versioned + .post({ + path: addInternalBasePath('transforms/_preview'), + access: 'internal', + }) + .addVersion( + { + version: '1', + validate: { + request: { + body: postTransformsPreviewRequestSchema, + }, + }, + }, + license.guardApiRoute(routeHandler) + ); +} diff --git a/x-pack/plugins/transform/server/routes/api/transforms_preview/route_handler.ts b/x-pack/plugins/transform/server/routes/api/transforms_preview/route_handler.ts new file mode 100644 index 0000000000000..2ce611260836e --- /dev/null +++ b/x-pack/plugins/transform/server/routes/api/transforms_preview/route_handler.ts @@ -0,0 +1,66 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; + +import type { RequestHandler } from '@kbn/core/server'; + +import type { PostTransformsPreviewRequestSchema } from '../../../../common/api_schemas/transforms'; +import { isLatestTransform } from '../../../../common/types/transform'; +import { isKeywordDuplicate } from '../../../../common/utils/field_utils'; + +import { wrapError, wrapEsError } from '../../utils/error_utils'; + +export const routeHandler: RequestHandler< + undefined, + undefined, + PostTransformsPreviewRequestSchema +> = async (ctx, req, res) => { + try { + const reqBody = req.body; + const esClient = (await ctx.core).elasticsearch.client; + const body = await esClient.asCurrentUser.transform.previewTransform( + { + body: reqBody, + }, + { maxRetries: 0 } + ); + if (isLatestTransform(reqBody)) { + // for the latest transform mappings properties have to be retrieved from the source + const fieldCapsResponse = await esClient.asCurrentUser.fieldCaps( + { + index: reqBody.source.index, + fields: '*', + include_unmapped: false, + }, + { maxRetries: 0 } + ); + + const fieldNamesSet = new Set(Object.keys(fieldCapsResponse.fields)); + + const fields = Object.entries( + fieldCapsResponse.fields as Record> + ).reduce((acc, [fieldName, fieldCaps]) => { + const fieldDefinition = Object.values(fieldCaps)[0]; + const isMetaField = fieldDefinition.type.startsWith('_') || fieldName === '_doc_count'; + if (isMetaField || isKeywordDuplicate(fieldName, fieldNamesSet)) { + return acc; + } + acc[fieldName] = { ...fieldDefinition }; + return acc; + }, {} as Record); + + body.generated_dest_index.mappings!.properties = fields as Record< + string, + estypes.MappingProperty + >; + } + return res.ok({ body }); + } catch (e) { + return res.customError(wrapError(wrapEsError(e))); + } +}; diff --git a/x-pack/plugins/transform/server/routes/api/transforms_single/register_route.ts b/x-pack/plugins/transform/server/routes/api/transforms_single/register_route.ts new file mode 100644 index 0000000000000..e79446d3962c0 --- /dev/null +++ b/x-pack/plugins/transform/server/routes/api/transforms_single/register_route.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. + */ + +import { addInternalBasePath } from '../../../../common/constants'; +import { + transformIdParamSchema, + type TransformIdParamSchema, +} from '../../../../common/api_schemas/common'; + +import type { RouteDependencies } from '../../../types'; + +import { routeHandler } from './route_handler'; + +export function registerRoute({ router, license }: RouteDependencies) { + /** + * @apiGroup Transforms + * + * @api {get} /internal/transform/transforms/:transformId Get transform + * @apiName GetTransform + * @apiDescription Returns a single transform + * + * @apiSchema (params) transformIdParamSchema + */ + router.versioned + .get({ + path: addInternalBasePath('transforms/{transformId}'), + access: 'internal', + }) + .addVersion( + { + version: '1', + validate: { + request: { + params: transformIdParamSchema, + }, + }, + }, + license.guardApiRoute(routeHandler) + ); +} diff --git a/x-pack/plugins/transform/server/routes/api/transforms_single/route_handler.ts b/x-pack/plugins/transform/server/routes/api/transforms_single/route_handler.ts new file mode 100644 index 0000000000000..623769707b0e2 --- /dev/null +++ b/x-pack/plugins/transform/server/routes/api/transforms_single/route_handler.ts @@ -0,0 +1,29 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type { RequestHandler } from '@kbn/core/server'; + +import type { TransformIdParamSchema } from '../../../../common/api_schemas/common'; + +import { wrapError, wrapEsError } from '../../utils/error_utils'; + +export const routeHandler: RequestHandler = async ( + ctx, + req, + res +) => { + const { transformId } = req.params; + try { + const esClient = (await ctx.core).elasticsearch.client; + const body = await esClient.asCurrentUser.transform.getTransform({ + transform_id: transformId, + }); + return res.ok({ body }); + } catch (e) { + return res.customError(wrapError(wrapEsError(e))); + } +}; diff --git a/x-pack/plugins/transform/server/routes/api/transforms_stats_all/register_route.ts b/x-pack/plugins/transform/server/routes/api/transforms_stats_all/register_route.ts new file mode 100644 index 0000000000000..0f2fa18b4665f --- /dev/null +++ b/x-pack/plugins/transform/server/routes/api/transforms_stats_all/register_route.ts @@ -0,0 +1,38 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; + +import { addInternalBasePath } from '../../../../common/constants'; + +import type { RouteDependencies } from '../../../types'; + +import { routeHandler } from './route_handler'; + +export function registerRoute({ router, license }: RouteDependencies) { + /** + * @apiGroup Transforms + * + * @api {get} /internal/transform/transforms/_stats Get transforms stats + * @apiName GetTransformsStats + * @apiDescription Returns transforms stats + */ + router.versioned + .get({ + path: addInternalBasePath('transforms/_stats'), + access: 'internal', + }) + .addVersion( + { + version: '1', + validate: false, + }, + license.guardApiRoute( + routeHandler + ) + ); +} diff --git a/x-pack/plugins/transform/server/routes/api/transforms_stats_all/route_handler.ts b/x-pack/plugins/transform/server/routes/api/transforms_stats_all/route_handler.ts new file mode 100644 index 0000000000000..901afdd4ea809 --- /dev/null +++ b/x-pack/plugins/transform/server/routes/api/transforms_stats_all/route_handler.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 * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; + +import type { RequestHandler } from '@kbn/core/server'; + +import { TransformRequestHandlerContext } from '../../../services/license'; + +import { wrapError, wrapEsError } from '../../utils/error_utils'; + +export const routeHandler: RequestHandler< + estypes.TransformGetTransformStatsResponse, + undefined, + undefined, + TransformRequestHandlerContext +> = async (ctx, req, res) => { + try { + const esClient = (await ctx.core).elasticsearch.client; + const body = await esClient.asCurrentUser.transform.getTransformStats( + { + size: 1000, + transform_id: '_all', + }, + { maxRetries: 0 } + ); + return res.ok({ body }); + } catch (e) { + return res.customError(wrapError(wrapEsError(e))); + } +}; diff --git a/x-pack/plugins/transform/server/routes/api/transforms_stats_single/register_route.ts b/x-pack/plugins/transform/server/routes/api/transforms_stats_single/register_route.ts new file mode 100644 index 0000000000000..8c06c95892116 --- /dev/null +++ b/x-pack/plugins/transform/server/routes/api/transforms_stats_single/register_route.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. + */ + +import { + transformIdParamSchema, + type TransformIdParamSchema, +} from '../../../../common/api_schemas/common'; +import { addInternalBasePath } from '../../../../common/constants'; + +import type { RouteDependencies } from '../../../types'; + +import { routeHandler } from './route_handler'; + +export function registerRoute({ router, license }: RouteDependencies) { + /** + * @apiGroup Transforms + * + * @api {get} /internal/transform/transforms/:transformId/_stats Get transform stats + * @apiName GetTransformStats + * @apiDescription Returns stats for a single transform + * + * @apiSchema (params) transformIdParamSchema + */ + router.versioned + .get({ + path: addInternalBasePath('transforms/{transformId}/_stats'), + access: 'internal', + }) + .addVersion( + { + version: '1', + validate: { + request: { + params: transformIdParamSchema, + }, + }, + }, + license.guardApiRoute(routeHandler) + ); +} diff --git a/x-pack/plugins/transform/server/routes/api/transforms_stats_single/route_handler.ts b/x-pack/plugins/transform/server/routes/api/transforms_stats_single/route_handler.ts new file mode 100644 index 0000000000000..29c6f39e7126b --- /dev/null +++ b/x-pack/plugins/transform/server/routes/api/transforms_stats_single/route_handler.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 { RequestHandler } from '@kbn/core/server'; + +import type { TransformIdParamSchema } from '../../../../common/api_schemas/common'; + +import type { TransformRequestHandlerContext } from '../../../services/license'; + +import { wrapError, wrapEsError } from '../../utils/error_utils'; + +export const routeHandler: RequestHandler< + TransformIdParamSchema, + undefined, + undefined, + TransformRequestHandlerContext +> = async (ctx, req, res) => { + const { transformId } = req.params; + try { + const esClient = (await ctx.core).elasticsearch.client; + const body = await esClient.asCurrentUser.transform.getTransformStats( + { + transform_id: transformId, + }, + { maxRetries: 0 } + ); + return res.ok({ body }); + } catch (e) { + return res.customError(wrapError(wrapEsError(e))); + } +}; diff --git a/x-pack/plugins/transform/server/routes/api/transforms_update/register_route.ts b/x-pack/plugins/transform/server/routes/api/transforms_update/register_route.ts new file mode 100644 index 0000000000000..366b4ea32fc92 --- /dev/null +++ b/x-pack/plugins/transform/server/routes/api/transforms_update/register_route.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 { + transformIdParamSchema, + type TransformIdParamSchema, +} from '../../../../common/api_schemas/common'; +import { + postTransformsUpdateRequestSchema, + type PostTransformsUpdateRequestSchema, +} from '../../../../common/api_schemas/update_transforms'; +import { addInternalBasePath } from '../../../../common/constants'; + +import type { RouteDependencies } from '../../../types'; + +import { routeHandler } from './route_handler'; + +export function registerRoute({ router, license }: RouteDependencies) { + /** + * @apiGroup Transforms + * + * @api {post} /internal/transform/transforms/:transformId/_update Post transform update + * @apiName PostTransformUpdate + * @apiDescription Updates a transform + * + * @apiSchema (params) transformIdParamSchema + * @apiSchema (body) postTransformsUpdateRequestSchema + */ + router.versioned + .post({ + path: addInternalBasePath('transforms/{transformId}/_update'), + access: 'internal', + }) + .addVersion( + { + version: '1', + validate: { + request: { + params: transformIdParamSchema, + body: postTransformsUpdateRequestSchema, + }, + }, + }, + license.guardApiRoute( + routeHandler + ) + ); +} diff --git a/x-pack/plugins/transform/server/routes/api/transforms_update/route_handler.ts b/x-pack/plugins/transform/server/routes/api/transforms_update/route_handler.ts new file mode 100644 index 0000000000000..9a88c4da3d48a --- /dev/null +++ b/x-pack/plugins/transform/server/routes/api/transforms_update/route_handler.ts @@ -0,0 +1,38 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type { RequestHandler } from '@kbn/core/server'; + +import type { TransformIdParamSchema } from '../../../../common/api_schemas/common'; +import type { PostTransformsUpdateRequestSchema } from '../../../../common/api_schemas/update_transforms'; + +import type { TransformRequestHandlerContext } from '../../../services/license'; + +import { wrapError } from '../../utils/error_utils'; + +export const routeHandler: RequestHandler< + TransformIdParamSchema, + undefined, + PostTransformsUpdateRequestSchema, + TransformRequestHandlerContext +> = async (ctx, req, res) => { + const { transformId } = req.params; + + try { + const esClient = (await ctx.core).elasticsearch.client; + const body = await esClient.asCurrentUser.transform.updateTransform({ + // @ts-expect-error query doesn't satisfy QueryDslQueryContainer from @elastic/elasticsearch + body: req.body, + transform_id: transformId, + }); + return res.ok({ + body, + }); + } catch (e) { + return res.customError(wrapError(e)); + } +}; diff --git a/x-pack/plugins/transform/server/routes/index.ts b/x-pack/plugins/transform/server/routes/index.ts index aec4417f2a421..d3d8bd48b8c0a 100644 --- a/x-pack/plugins/transform/server/routes/index.ts +++ b/x-pack/plugins/transform/server/routes/index.ts @@ -7,10 +7,38 @@ import { RouteDependencies } from '../types'; -import { registerFieldHistogramsRoutes } from './api/field_histograms'; -import { registerTransformsRoutes } from './api/transforms'; +import { registerRoute as registerFieldHistogramsRoute } from './api/field_histograms/register_route'; +import { registerRoute as registerAuditMessagesRoute } from './api/audit_messages/register_route'; +import { registerRoute as registerTransformsNodesRoute } from './api/transforms_nodes/register_route'; +import { registerRoute as registerTransformsAllRoute } from './api/transforms_all/register_route'; +import { registerRoute as registerTransformsSingleRoute } from './api/transforms_single/register_route'; +import { registerRoute as registerTransformsStatsAllRoute } from './api/transforms_stats_all/register_route'; +import { registerRoute as registerTransformsStatsSingleRoute } from './api/transforms_stats_single/register_route'; +import { registerRoute as registerTransformsCreateRoute } from './api/transforms_create/register_route'; +import { registerRoute as registerTransformsUpdateRoute } from './api/transforms_update/register_route'; +import { registerRoute as registerReauthorizeTransformsRoute } from './api/reauthorize_transforms/register_route'; +import { registerRoute as registerResetTransformsRoute } from './api/reset_transforms/register_route'; +import { registerRoute as registerTransformsPreviewRoute } from './api/transforms_preview/register_route'; +import { registerRoute as registerStartTransformsRoute } from './api/start_transforms/register_route'; +import { registerRoute as registerStopTransformsRoute } from './api/stop_transforms/register_route'; +import { registerRoute as registerDeleteTransformsRoute } from './api/delete_transforms/register_route'; +import { registerRoute as registerScheduleNowTransformsRoute } from './api/schedule_now_transforms/register_route'; export function registerRoutes(dependencies: RouteDependencies) { - registerFieldHistogramsRoutes(dependencies); - registerTransformsRoutes(dependencies); + registerFieldHistogramsRoute(dependencies); + registerAuditMessagesRoute(dependencies); + registerTransformsNodesRoute(dependencies); + registerTransformsAllRoute(dependencies); + registerTransformsSingleRoute(dependencies); + registerTransformsStatsAllRoute(dependencies); + registerTransformsStatsSingleRoute(dependencies); + registerTransformsCreateRoute(dependencies); + registerTransformsUpdateRoute(dependencies); + registerReauthorizeTransformsRoute(dependencies); + registerResetTransformsRoute(dependencies); + registerTransformsPreviewRoute(dependencies); + registerStartTransformsRoute(dependencies); + registerStopTransformsRoute(dependencies); + registerDeleteTransformsRoute(dependencies); + registerScheduleNowTransformsRoute(dependencies); } diff --git a/x-pack/plugins/transform/server/routes/api/error_utils.ts b/x-pack/plugins/transform/server/routes/utils/error_utils.ts similarity index 100% rename from x-pack/plugins/transform/server/routes/api/error_utils.ts rename to x-pack/plugins/transform/server/routes/utils/error_utils.ts diff --git a/x-pack/plugins/transform/server/services/license.ts b/x-pack/plugins/transform/server/services/license.ts index 3a22b2e6bd27f..4a5591bbe74e8 100644 --- a/x-pack/plugins/transform/server/services/license.ts +++ b/x-pack/plugins/transform/server/services/license.ts @@ -36,7 +36,7 @@ interface SetupSettings { coreStart: CoreStart; } -type TransformRequestHandlerContext = CustomRequestHandlerContext<{ +export type TransformRequestHandlerContext = CustomRequestHandlerContext<{ alerting?: AlertingApiRequestHandlerContext; }>; diff --git a/x-pack/plugins/translations/server/index.ts b/x-pack/plugins/translations/server/index.ts index dfa3a2aa7211f..f15dc4cc730a7 100644 --- a/x-pack/plugins/translations/server/index.ts +++ b/x-pack/plugins/translations/server/index.ts @@ -15,4 +15,4 @@ class TranslationsPlugin { } } -export const plugin = () => new TranslationsPlugin(); +export const plugin = async () => new TranslationsPlugin(); diff --git a/x-pack/plugins/translations/translations/fr-FR.json b/x-pack/plugins/translations/translations/fr-FR.json index ca26a40d31d22..c656e54ee8f5f 100644 --- a/x-pack/plugins/translations/translations/fr-FR.json +++ b/x-pack/plugins/translations/translations/fr-FR.json @@ -4937,7 +4937,6 @@ "management.settings.categoryNames.visualizationsLabel": "Visualisations", "management.settings.changeImageLinkText": "Modifier l'image", "management.settings.customSettingTooltip": "Paramètre personnalisé", - "management.settings.field.codeEditorSyntaxErrorMessage": "Syntaxe JSON non valide", "management.settings.field.customSettingAriaLabel": "Paramètre personnalisé", "management.settings.field.imageChangeErrorMessage": "Impossible d’enregistrer l'image", "management.settings.field.invalidIconLabel": "Non valide", @@ -20096,17 +20095,7 @@ "xpack.indexLifecycleMgmt.hotPhase.maximumPrimaryShardDocsLabel": "Maximum de documents dans la partition principale", "xpack.indexLifecycleMgmt.hotPhase.maximumPrimaryShardSizeLabel": "Taille de partition principale maximale", "xpack.indexLifecycleMgmt.hotPhase.rolloverFieldTitle": "Substitution", - "xpack.indexLifecycleMgmt.indexLifecycleMgmtSummary.actionStatusTitle": "Statut d'action", - "xpack.indexLifecycleMgmt.indexLifecycleMgmtSummary.headers.currentActionHeader": "Action actuelle", - "xpack.indexLifecycleMgmt.indexLifecycleMgmtSummary.headers.currentActionTimeHeader": "Temps de l'action actuelle", - "xpack.indexLifecycleMgmt.indexLifecycleMgmtSummary.headers.currentPhaseHeader": "Phase actuelle", - "xpack.indexLifecycleMgmt.indexLifecycleMgmtSummary.headers.failedStepHeader": "Étape ayant échoué", - "xpack.indexLifecycleMgmt.indexLifecycleMgmtSummary.headers.lifecyclePolicyHeader": "Stratégie de cycle de vie", "xpack.indexLifecycleMgmt.indexLifecycleMgmtSummary.phaseDefinitionTitle": "Définition de la phase", - "xpack.indexLifecycleMgmt.indexLifecycleMgmtSummary.showPhaseDefinitionButton": "Afficher la définition", - "xpack.indexLifecycleMgmt.indexLifecycleMgmtSummary.showPhaseDefinitionDescriptionTitle": "Définition de la phase", - "xpack.indexLifecycleMgmt.indexLifecycleMgmtSummary.summaryErrorMessage": "Erreur de cycle de vie des index", - "xpack.indexLifecycleMgmt.indexLifecycleMgmtSummary.summaryTitle": "Gestion du cycle de vie des index", "xpack.indexLifecycleMgmt.indexManagementTable.addLifecyclePolicyConfirmModal.addPolicyButtonText": "Ajouter une stratégie", "xpack.indexLifecycleMgmt.indexManagementTable.addLifecyclePolicyConfirmModal.addPolicyToIndexError": "Erreur lors de l'ajout d'une stratégie à l'index", "xpack.indexLifecycleMgmt.indexManagementTable.addLifecyclePolicyConfirmModal.cancelButtonText": "Annuler", @@ -23521,8 +23510,6 @@ "xpack.maps.blendedVectorLayer.clusteredLayerName": "{displayName} en cluster", "xpack.maps.common.esSpatialRelation.clusterFilterLabel": "intersecte le cluster {gridId}", "xpack.maps.deleteLayerConfirmModal.multiLayerWarning": "Le retrait de ce calque retire également {numChildren} {numChildren, plural, one {calque imbriqué} many {les calques} other {les calques}}.", - "xpack.maps.distanceSource.requestDescription": "Obtenir des indicateurs de la vue de données : {dataViewName} ; champ géospatial : {geoFieldName}", - "xpack.maps.distanceSource.requestName": "{leftSourceName} à distance de la requête de liaison", "xpack.maps.embeddable.boundsFilterLabel": "{geoFieldsLabel} dans les limites de la carte", "xpack.maps.es_geo_utils.convert.unsupportedGeometryTypeErrorMessage": "Conversion de la géométrie {geometryType} en geojson impossible ; non pris en charge", "xpack.maps.es_geo_utils.distanceFilterAlias": "dans un rayon de {distanceKm} km de {pointLabel}", @@ -23536,10 +23523,6 @@ "xpack.maps.esSearch.topHitsEntitiesCountMsg": "{entityCount} entités trouvées.", "xpack.maps.esSearch.topHitsResultsTrimmedMsg": "Résultats limités aux {entityCount} premières entités sur environ {totalEntities}.", "xpack.maps.esSearch.topHitsSizeMsg": "Affichage des {topHitsSize} premiers documents par entité.", - "xpack.maps.esSearchSource.requestDescription": "Obtenir des documents de la vue de données : {dataViewName} ; champ géospatial : {geoFieldName}", - "xpack.maps.esSearchSource.requestName": "Requête de documents de {layerName}", - "xpack.maps.esSearchSource.topHits.requestDescription": "Obtenir les premiers résultats de la vue de données : {dataViewName} ; entités : {entitiesFieldName} ; champ géospatial : {geoFieldName}", - "xpack.maps.esSearchSource.topHits.requestName": "Requête des premiers résultats de {layerName}", "xpack.maps.fileUpload.trimmedResultsMsg": "Résultats limités à {numFeatures} fonctionnalités, {previewCoverage} % du fichier.", "xpack.maps.filterByMapExtentMenuItem.displayName": "Filtrer {containerLabel} selon les limites de la carte", "xpack.maps.filterByMapExtentMenuItem.displayNameTooltip": "Quand vous vous déplacez sur la carte ou que vous zoomez, le {containerLabel} se met à jour pour afficher uniquement les données visibles dans les limites de la carte.", @@ -23562,7 +23545,6 @@ "xpack.maps.mask.maskLabel": "Masquer {hideNoun}", "xpack.maps.mask.whenJoinMetric": "{whenLabel} l'indicateur de jonction", "xpack.maps.maskLegend.is": "{aggLabel} est", - "xpack.maps.pewPew.requestName": "Requête de chemins de {layerName}", "xpack.maps.scalingDocs.clustersDetails": "Affichez les clusters lorsque les résultats dépassent {maxResultWindow} documents. Affichez les documents lorsqu'il y a moins de {maxResultWindow} résultats.", "xpack.maps.scalingDocs.limitDetails": "Affichez les fonctionnalités des {maxResultWindow} premiers documents.", "xpack.maps.scalingDocs.maxResultWindow": "Contrainte {maxResultWindow} fournie par le paramètre d'index {link}.", @@ -23578,15 +23560,8 @@ "xpack.maps.source.emsTileSourceDescription": "Service de fond de carte de {host}", "xpack.maps.source.esAggSource.topTermLabel": "{fieldLabel} principal", "xpack.maps.source.esGeoGrid.groupBy.termsDescription": "Créez un suivi pour les {maxTermsTracks} termes principaux. Le suivi est tronqué lorsque le nombre d'éléments dépasse la limite.", - "xpack.maps.source.esGeoLine.entityRequestDescription": "Obtenir des entités au sein de la mémoire tampon de la carte depuis la vue de données  : {dataViewName} ; entités : {splitFieldName}", - "xpack.maps.source.esGeoLine.timeSeriesTrackRequestDescription": "Obtenir des suivis de la vue de données : {dataViewName} ; champ géospatial : {geoFieldName}", - "xpack.maps.source.esGeoLine.trackRequestDescription": "Obtenir des pistes pour des entités {numEntities} depuis la vue de données : {dataViewName} ; champ géospatial : {geoFieldName}", "xpack.maps.source.esGeoLineDisabledReason": "{title} requiert une licence Gold.", - "xpack.maps.source.esGrid.compositeInspector.requestName": "Requête composite de {layerName} {bucketsName} ({requestCount})", - "xpack.maps.source.esGrid.compositeInspectorDescription": "Obtenir {bucketsName} de la vue de données : {dataViewName} ; champ géospatial : {geoFieldName}", "xpack.maps.source.esGrid.compositePaginationErrorMessage": "{layerName} génère trop de requêtes. Réduisez \"Résolution de la grille\" et/ou réduisez le nombre d'indicateurs de premier terme.", - "xpack.maps.source.esGrid.inspector.requestDescription": "Obtenir {bucketsName} de la vue de données : {dataViewName} ; champ géospatial : {geoFieldName}", - "xpack.maps.source.esGrid.inspector.requestName": "Requête de {layerName} {bucketsName}", "xpack.maps.source.esGrid.resolutionParamErrorMessage": "Paramètre de résolution de grille non reconnu : {resolution}", "xpack.maps.source.esJoin.countLabel": "Nombre de {indexPatternLabel}", "xpack.maps.source.esSearch.clusterScalingLabel": "Afficher les clusters lorsque les résultats dépassent {maxResultWindow}", @@ -23595,18 +23570,14 @@ "xpack.maps.source.esSearch.loadTooltipPropertiesErrorMsg": "Document introuvable, _id : {docId}", "xpack.maps.source.esSearch.mvtScalingJoinMsg": "Les tuiles vectorielles prennent en charge une seule liaison de terme. Votre calque a {numberOfJoins} liaisons. Le passage aux tuiles vectorielles conservera la première liaison de terme et supprimera toutes les autres liaisons de votre configuration de calque.", "xpack.maps.source.esSource.noGeoFieldErrorMessage": "La vue de données \"{indexPatternLabel}\" ne contient plus le champ géographique \"{geoField}\"", - "xpack.maps.source.esSource.requestFailedErrorMessage": "Échec de la demande de recherche Elasticsearch, erreur : {message}", "xpack.maps.source.esSource.stylePropsMetaRequestName": "{layerName} - Métadonnées", "xpack.maps.source.MVTSingleLayerVectorSourceEditor.urlHelpMessage": "URL du service de cartographie vectoriel .mvt. Par exemple, {url}", - "xpack.maps.source.pewPew.inspectorDescription": "Obtenir des chemins depuis la vue de données : {dataViewName} ; source : {sourceFieldName} ; destination : {destFieldName}", "xpack.maps.spatialJoin.wizardForm.withinExpressionValue": "{distance} {units} de fonctionnalités de calque", "xpack.maps.spatialJoinExpression.noDataViewTitle": "Impossible de charger la vue de données {dataViewId}.", "xpack.maps.spatialJoinExpression.value": "fonctionnalités de {geoField}", "xpack.maps.style.fieldSelect.OriginLabel": "Champs de {fieldOrigin}", "xpack.maps.termJoinExpression.topTerms": "{size} principal", "xpack.maps.termJoinExpression.value": "termes {topTerms} de {term}", - "xpack.maps.termSource.requestDescription": "Obtenir des indicateurs depuis la vue de données : {dataViewName} ; champ de terme : {termFieldName}", - "xpack.maps.termSource.requestName": "Requête de liaison de terme de {leftSourceName}", "xpack.maps.tiles.resultsCompleteMsg": "{countPrefix}{count} documents trouvés.", "xpack.maps.tiles.resultsTrimmedMsg": "Les résultats sont limités à {countPrefix}{count} documents.", "xpack.maps.tooltip.pageNumerText": "{pageNumber} de {total}", @@ -24046,8 +24017,6 @@ "xpack.maps.source.esGeoLine.sortFieldPlaceholder": "Sélectionner le champ de tri", "xpack.maps.source.esGeoLine.splitFieldLabel": "Entité", "xpack.maps.source.esGeoLine.splitFieldPlaceholder": "Sélectionner un champ d'entité", - "xpack.maps.source.esGeoLine.timeSeriesTrackRequestName": "Requêtes de piste \"{layerName}\" (séries temporelles)", - "xpack.maps.source.esGeoLine.trackRequestName": "Requêtes de piste \"{layerName}\" (termes)", "xpack.maps.source.esGeoLine.trackSettingsLabel": "Pistes", "xpack.maps.source.esGeoLineDescription": "Créer des lignes à partir de points", "xpack.maps.source.esGeoLineTitle": "Pistes", @@ -24090,7 +24059,6 @@ "xpack.maps.source.esSearch.useMVTVectorTiles": "Utiliser les tuiles vectorielles", "xpack.maps.source.esSearchDescription": "Points, lignes et polygones d'Elasticsearch", "xpack.maps.source.esSearchTitle": "Documents", - "xpack.maps.source.esSource.stylePropsMetaRequestDescription": "Recherche Elasticsearch récupérant les métadonnées de champ utilisées pour le calcul des champs de symbolisation.", "xpack.maps.source.esTopHitsSearch.sortFieldLabel": "Champ de tri", "xpack.maps.source.esTopHitsSearch.sortOrderLabel": "Ordre de tri", "xpack.maps.source.geofieldLabel": "Champ géospatial", @@ -29997,7 +29965,6 @@ "xpack.osquery.updatePack.successToastMessageText": "Mise à jour réussie du pack \"{packName}\"", "xpack.osquery.viewSavedQuery.pageTitle": "Détails de \"{savedQueryId}\"", "xpack.osquery.action_details.fetchError": "Erreur lors de la récupération des détails d'action", - "xpack.osquery.action_policy_details.fetchError": "Erreur lors de la récupération des détails de politique", "xpack.osquery.action_results.errorSearchDescription": "Une erreur s'est produite lors de la recherche des résultats d'action", "xpack.osquery.action_results.failSearchDescription": "Impossible de récupérer les résultats d'action", "xpack.osquery.action_results.fetchError": "Erreur lors de la récupération des résultats d'action", @@ -30018,7 +29985,6 @@ "xpack.osquery.addSavedQuery.form.saveQueryButtonLabel": "Enregistrer la recherche", "xpack.osquery.addSavedQuery.pageTitle": "Ajouter une recherche enregistrée", "xpack.osquery.addSavedQuery.viewSavedQueriesListTitle": "Afficher toutes les recherches enregistrées", - "xpack.osquery.agent_groups.fetchError": "Erreur lors de la récupération des groupes d'agents", "xpack.osquery.agent_policies.fetchError": "Erreur lors de la récupération des politiques d'agents", "xpack.osquery.agent_policy_details.fetchError": "Erreur lors de la récupération des détails de politiques d'agents", "xpack.osquery.agent_status.fetchError": "Erreur lors de la récupération du statut des agents", @@ -30678,7 +30644,6 @@ "xpack.reporting.diagnostic.browserMissingDependency": "Le navigateur n'a pas pu démarrer correctement en raison de dépendances système manquantes. Veuillez consulter {url}", "xpack.reporting.diagnostic.browserMissingFonts": "Le navigateur n'a pas réussi à localiser de police par défaut. Consultez {url} pour corriger ce problème.", "xpack.reporting.diagnostic.noUsableSandbox": "Impossible d'utiliser la sandbox Chromium. Vous pouvez la désactiver à vos risques et périls avec \"xpack.screenshotting.browser.chromium.disableSandbox\". Veuillez consulter {url}", - "xpack.reporting.exportTypes.common.failedToDecryptReportJobDataErrorMessage": "Impossible de déchiffrer les données de la tâche de reporting. Veuillez vous assurer que {encryptionKey} est défini et générez à nouveau ce rapport. {err}", "xpack.reporting.jobResponse.errorHandler.notAuthorized": "Désolé, vous n'êtes pas autorisé à afficher ou supprimer les rapports {jobtype}", "xpack.reporting.jobsQuery.deleteError": "Impossible de supprimer le rapport : {error}", "xpack.reporting.jobStatusDetail.attemptXofY": "Tentative {attempts} sur {max_attempts}.", @@ -30733,7 +30698,6 @@ "xpack.reporting.deprecations.reportingRoleUsers.manualStepThree": "Sous Gestion > Sécurité > Rôles, créez un ou plusieurs rôles permettant d'accorder le privilège de l'application Kibana à Reporting.", "xpack.reporting.deprecations.reportingRoleUsers.manualStepTwo": "Supprimez le paramètre \"xpack.reporting.roles.allow\" du fichier kibana.yml, le cas échéant.", "xpack.reporting.errorHandler.unknownError": "Erreur inconnue", - "xpack.reporting.exportTypes.common.missingJobHeadersErrorMessage": "Les en-têtes de tâche sont manquants", "xpack.reporting.jobCreatedBy.unknownUserPlaceholderText": "Inconnu", "xpack.reporting.jobResponse.errorHandler.unknownError": "Erreur inconnue", "xpack.reporting.jobStatusDetail.deprecatedText": "Il s'agit d'un type d'exportation déclassé. L'automatisation de ce rapport devra être à nouveau créée pour une question de compatibilité avec les futures versions de Kibana.", @@ -35060,7 +35024,6 @@ "xpack.securitySolution.endpoint.policyNotFound": "Politique introuvable !", "xpack.securitySolution.endpoint.policyResponse.backLinkTitle": "Détails de point de terminaison", "xpack.securitySolution.endpoint.policyResponse.title": "Réponse de politique", - "xpack.securitySolution.endpoint.protectionUpdates.automaticUpdates.enabled": "Le manifeste est toujours mis à jour vers la dernière version disponible. Si vous voulez contrôler manuellement les mises à jour, désactivez \"Mettre à jour le manifeste automatiquement\".", "xpack.securitySolution.endpoint.protectionUpdates.automaticUpdates.enabledTitle": "Mises à jour automatiques activées", "xpack.securitySolution.endpoint.protectionUpdates.cancel": "Annuler", "xpack.securitySolution.endpoint.protectionUpdates.deployedVersion.label": "Version actuellement déployée", @@ -40465,9 +40428,7 @@ "xpack.transform.forceDeleteTransformMessage": "Supprimer {count} {count, plural, one {transformation} many {transformations} other {transformations}}", "xpack.transform.managedTransformsWarningCallout": "{count, plural, one {Cette transformation} many {Au moins l''une de ces transformations} other {Au moins l''une de ces transformations}} est préconfigurée par Elastic. Le fait de {action} {count, plural, one {la} many {les} other {les}} avec une heure de fin spécifique peut avoir un impact sur d'autres éléments du produit.", "xpack.transform.multiTransformActionsMenu.transformsCount": "Sélection effectuée de {count} {count, plural, one {transformation} many {transformations} other {transformations}}", - "xpack.transform.stepCreateForm.createDataViewErrorMessage": "Une erreur est survenue lors de la création de la vue de données Kibana {dataViewName} :", "xpack.transform.stepCreateForm.createTransformErrorMessage": "Une erreur s'est produite lors de la création de la transformation {transformId} :", - "xpack.transform.stepCreateForm.duplicateDataViewErrorMessage": "Une erreur est survenue lors de la création de la vue de données Kibana {dataViewName} : La vue de données existe déjà.", "xpack.transform.stepDefineForm.invalidKuerySyntaxErrorMessageQueryBar": "Requête non valide : {queryErrorMessage}", "xpack.transform.stepDefineForm.queryPlaceholderKql": "Par exemple, {example}", "xpack.transform.stepDefineForm.queryPlaceholderLucene": "Par exemple, {example}", @@ -43323,10 +43284,12 @@ "observabilityAlertDetails.alertThresholdTimeRangeRect.detailsTooltip": "Seuil", "randomSampling.ui.sliderControl.accuracyLabel": "Précision", "randomSampling.ui.sliderControl.performanceLabel": "Performances", - "reactPackages.mountPointPortal.errorMessage": "Erreur lors du rendu du contenu du portail.", + "reporting.commonExportTypesHelpers.missingJobHeadersErrorMessage": "Les en-têtes de tâche sont manquants", + "reporting.commonExportTypesHelpers.failedToDecryptReportJobDataErrorMessage": "Impossible de déchiffrer les données de la tâche de reporting. Veuillez vous assurer que {encryptionKey} est défini et générez à nouveau ce rapport. {err}", "reporting.common.browserCouldNotLaunchErrorMessage": "Impossible de générer des captures d'écran, car le navigateur ne s’est pas lancé. Consultez les logs de serveur pour en savoir plus.", "reporting.common.cloud.insufficientSystemMemoryError": "Impossible de générer ce rapport en raison d’un manque de mémoire.", "reporting.common.pdfWorkerOutOfMemoryErrorMessage": "Impossible de générer un PDF en raison d’un manque de mémoire. Essayez de réduire la taille du PDF et relancez ce rapport.", + "reactPackages.mountPointPortal.errorMessage": "Erreur lors du rendu du contenu du portail.", "savedObjectsFinder.advancedSettings.listingLimitText": "Nombre d'objets à récupérer pour les pages de listing", "savedObjectsFinder.advancedSettings.listingLimitTitle": "Limite de listing d’objets", "savedObjectsFinder.advancedSettings.perPageText": "Nombre d'objets à afficher par page dans la boîte de dialogue de chargement", diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index 18ff35c3bb09d..157391ad9a6ff 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -4952,7 +4952,6 @@ "management.settings.categoryNames.visualizationsLabel": "ビジュアライゼーション", "management.settings.changeImageLinkText": "画像を変更", "management.settings.customSettingTooltip": "カスタム設定", - "management.settings.field.codeEditorSyntaxErrorMessage": "無効な JSON 構文", "management.settings.field.customSettingAriaLabel": "カスタム設定", "management.settings.field.imageChangeErrorMessage": "画像を保存できませんでした", "management.settings.field.invalidIconLabel": "無効", @@ -20109,17 +20108,7 @@ "xpack.indexLifecycleMgmt.hotPhase.maximumPrimaryShardDocsLabel": "主シャードの最大ドキュメント数", "xpack.indexLifecycleMgmt.hotPhase.maximumPrimaryShardSizeLabel": "最大プライマリシャードサイズ", "xpack.indexLifecycleMgmt.hotPhase.rolloverFieldTitle": "ロールオーバー", - "xpack.indexLifecycleMgmt.indexLifecycleMgmtSummary.actionStatusTitle": "アクションステータス", - "xpack.indexLifecycleMgmt.indexLifecycleMgmtSummary.headers.currentActionHeader": "現在のステータス", - "xpack.indexLifecycleMgmt.indexLifecycleMgmtSummary.headers.currentActionTimeHeader": "現在のアクション時間", - "xpack.indexLifecycleMgmt.indexLifecycleMgmtSummary.headers.currentPhaseHeader": "現在のフェーズ", - "xpack.indexLifecycleMgmt.indexLifecycleMgmtSummary.headers.failedStepHeader": "失敗したステップ", - "xpack.indexLifecycleMgmt.indexLifecycleMgmtSummary.headers.lifecyclePolicyHeader": "ライフサイクルポリシー", "xpack.indexLifecycleMgmt.indexLifecycleMgmtSummary.phaseDefinitionTitle": "フェーズ検知", - "xpack.indexLifecycleMgmt.indexLifecycleMgmtSummary.showPhaseDefinitionButton": "フェーズ検知を表示", - "xpack.indexLifecycleMgmt.indexLifecycleMgmtSummary.showPhaseDefinitionDescriptionTitle": "フェーズ検知", - "xpack.indexLifecycleMgmt.indexLifecycleMgmtSummary.summaryErrorMessage": "インデックスライフサイクルエラー", - "xpack.indexLifecycleMgmt.indexLifecycleMgmtSummary.summaryTitle": "インデックスライフサイクル管理", "xpack.indexLifecycleMgmt.indexManagementTable.addLifecyclePolicyConfirmModal.addPolicyButtonText": "ポリシーを追加", "xpack.indexLifecycleMgmt.indexManagementTable.addLifecyclePolicyConfirmModal.addPolicyToIndexError": "インデックスへのポリシーの追加中にエラーが発生しました", "xpack.indexLifecycleMgmt.indexManagementTable.addLifecyclePolicyConfirmModal.cancelButtonText": "キャンセル", @@ -23535,8 +23524,6 @@ "xpack.maps.blendedVectorLayer.clusteredLayerName": "クラスター化された{displayName}", "xpack.maps.common.esSpatialRelation.clusterFilterLabel": "クラスター{gridId}と交差します", "xpack.maps.deleteLayerConfirmModal.multiLayerWarning": "このレイヤーを削除すと、{numChildren}個のネストされた{numChildren, plural, other {レイヤー}}も削除されます。", - "xpack.maps.distanceSource.requestDescription": "データビューからメトリックを取得します:{dataViewName}、地理空間フィールド:{geoFieldName}", - "xpack.maps.distanceSource.requestName": "距離結合リクエスト内の{leftSourceName}", "xpack.maps.embeddable.boundsFilterLabel": "マップ境界内の{geoFieldsLabel}", "xpack.maps.es_geo_utils.convert.unsupportedGeometryTypeErrorMessage": "{geometryType} ジオメトリから Geojson に変換できません。サポートされていません", "xpack.maps.es_geo_utils.distanceFilterAlias": "{pointLabel}の{distanceKm}km以内", @@ -23550,10 +23537,6 @@ "xpack.maps.esSearch.topHitsEntitiesCountMsg": "{entityCount}エンティティが見つかりました。", "xpack.maps.esSearch.topHitsResultsTrimmedMsg": "結果は~{totalEntities}の{entityCount}エンティティに制限されています。", "xpack.maps.esSearch.topHitsSizeMsg": "エンティティごとに上位の{topHitsSize}ドキュメントを表示しています。", - "xpack.maps.esSearchSource.requestDescription": "データビューからドキュメントを取得します:{dataViewName}、地理空間フィールド:{geoFieldName}", - "xpack.maps.esSearchSource.requestName": "{layerName}ドキュメントリクエスト", - "xpack.maps.esSearchSource.topHits.requestDescription": "データビューから上位の一致を取得します:{dataViewName}、表現:{entitiesFieldName}、地理空間フィールド:{geoFieldName}", - "xpack.maps.esSearchSource.topHits.requestName": "{layerName}の上位の一致リクエスト", "xpack.maps.fileUpload.trimmedResultsMsg": "結果は{numFeatures}機能、ファイルの{previewCoverage}%に制限されています。", "xpack.maps.filterByMapExtentMenuItem.displayName": "マップ境界で{containerLabel}をフィルター", "xpack.maps.filterByMapExtentMenuItem.displayNameTooltip": "マップをズームおよびパンすると、{containerLabel}が更新され、マップ境界に表示されるデータのみが表示されます。", @@ -23576,7 +23559,6 @@ "xpack.maps.mask.maskLabel": "{hideNoun}を非表示", "xpack.maps.mask.whenJoinMetric": "{whenLabel}結合メトリック", "xpack.maps.maskLegend.is": "{aggLabel}は", - "xpack.maps.pewPew.requestName": "{layerName}パスリクエスト", "xpack.maps.scalingDocs.clustersDetails": "結果が{maxResultWindow}ドキュメントを超えたときにクラスターを表示します。結果が{maxResultWindow}未満のときにドキュメントを表示します。", "xpack.maps.scalingDocs.limitDetails": "最初の{maxResultWindow}ドキュメントから特徴量を表示します。", "xpack.maps.scalingDocs.maxResultWindow": "{link}のインデックス設定によって提供される{maxResultWindow}制約。", @@ -23592,15 +23574,8 @@ "xpack.maps.source.emsTileSourceDescription": "{host}からのベースマップサービス", "xpack.maps.source.esAggSource.topTermLabel": "上位{fieldLabel}", "xpack.maps.source.esGeoGrid.groupBy.termsDescription": "上位{maxTermsTracks}語句のトラックを作成します。ポイント数が上限を超えると、トラックは切り捨てられます。", - "xpack.maps.source.esGeoLine.entityRequestDescription": "データビューからマップバッファー内の表現を取得します:{dataViewName}、表現:{splitFieldName}", - "xpack.maps.source.esGeoLine.timeSeriesTrackRequestDescription": "データビューからトラックを取得します:{dataViewName}、地理空間フィールド:{geoFieldName}", - "xpack.maps.source.esGeoLine.trackRequestDescription": "データビューから{numEntities}個の表現のトラックを取得します:{dataViewName}、地理空間フィールド:{geoFieldName}", "xpack.maps.source.esGeoLineDisabledReason": "{title}には Gold ライセンスが必要です。", - "xpack.maps.source.esGrid.compositeInspector.requestName": "{layerName} {bucketsName}複合リクエスト({requestCount})", - "xpack.maps.source.esGrid.compositeInspectorDescription": "データビューから{bucketsName}を取得します:{dataViewName}、地理空間フィールド:{geoFieldName}", "xpack.maps.source.esGrid.compositePaginationErrorMessage": "{layerName}はリクエスト過多の原因になります。「グリッド解像度」を下げるか、またはトップ用語「メトリック」の数を減らしてください。", - "xpack.maps.source.esGrid.inspector.requestDescription": "データビューから{bucketsName}を取得します:{dataViewName}、地理空間フィールド:{geoFieldName}", - "xpack.maps.source.esGrid.inspector.requestName": "{layerName} {bucketsName}リクエスト", "xpack.maps.source.esGrid.resolutionParamErrorMessage": "グリッド解像度パラメーターが認識されません: {resolution}", "xpack.maps.source.esJoin.countLabel": "{indexPatternLabel}のカウント", "xpack.maps.source.esSearch.clusterScalingLabel": "結果が{maxResultWindow}を超えたらクラスターを表示", @@ -23609,18 +23584,14 @@ "xpack.maps.source.esSearch.loadTooltipPropertiesErrorMsg": "ドキュメントが見つかりません。_id: {docId}", "xpack.maps.source.esSearch.mvtScalingJoinMsg": "ベクトルタイルは1つの用語結合をサポートします。レイヤーには{numberOfJoins}個の結合があります。ベクトルタイルに切り替えると、最初の結合が保持され、すべての他の用語結合がレイヤー構成から削除されます。", "xpack.maps.source.esSource.noGeoFieldErrorMessage": "データビュー\"{indexPatternLabel}\"には現在ジオフィールド\"{geoField}\"が含まれていません", - "xpack.maps.source.esSource.requestFailedErrorMessage": "Elasticsearch検索リクエストを実行できませんでした。エラー:{message}", "xpack.maps.source.esSource.stylePropsMetaRequestName": "{layerName} - メタデータ", "xpack.maps.source.MVTSingleLayerVectorSourceEditor.urlHelpMessage": ".mvtベクトルタイルサービスのURL。例:{url}", - "xpack.maps.source.pewPew.inspectorDescription": "データビューからパスを取得します:{dataViewName}、ソース:{sourceFieldName}、デスティネーション:{destFieldName}", "xpack.maps.spatialJoin.wizardForm.withinExpressionValue": "レイヤー特徴量の{distance} {units}", "xpack.maps.spatialJoinExpression.noDataViewTitle": "データビュー{dataViewId}を読み込めません。", "xpack.maps.spatialJoinExpression.value": "{geoField}からの特徴量", "xpack.maps.style.fieldSelect.OriginLabel": "{fieldOrigin}からのフィールド", "xpack.maps.termJoinExpression.topTerms": "上位{size}", "xpack.maps.termJoinExpression.value": "{term}からの{topTerms}用語", - "xpack.maps.termSource.requestDescription": "データビューからメトリックを取得します:{dataViewName}、用語フィールド:{termFieldName}", - "xpack.maps.termSource.requestName": "{leftSourceName}用語結合リクエスト", "xpack.maps.tiles.resultsCompleteMsg": "{countPrefix}{count}件のドキュメントが見つかりました。", "xpack.maps.tiles.resultsTrimmedMsg": "結果は{countPrefix}{count}ドキュメントに制限されています。", "xpack.maps.tooltip.pageNumerText": "{pageNumber} / {total}", @@ -24060,8 +24031,6 @@ "xpack.maps.source.esGeoLine.sortFieldPlaceholder": "ソートフィールドを選択", "xpack.maps.source.esGeoLine.splitFieldLabel": "エンティティ", "xpack.maps.source.esGeoLine.splitFieldPlaceholder": "エンティティフィールドを選択", - "xpack.maps.source.esGeoLine.timeSeriesTrackRequestName": "'{layerName}'トラックリクエスト(時系列)", - "xpack.maps.source.esGeoLine.trackRequestName": "'{layerName}'トラックリクエスト(用語)", "xpack.maps.source.esGeoLine.trackSettingsLabel": "追跡", "xpack.maps.source.esGeoLineDescription": "ポイントから線を作成", "xpack.maps.source.esGeoLineTitle": "追跡", @@ -24104,7 +24073,6 @@ "xpack.maps.source.esSearch.useMVTVectorTiles": "ベクトルタイルを使用", "xpack.maps.source.esSearchDescription": "Elasticsearch の点、線、多角形", "xpack.maps.source.esSearchTitle": "ドキュメント", - "xpack.maps.source.esSource.stylePropsMetaRequestDescription": "シンボル化バンドを計算するために使用されるフィールドメタデータを取得するElasticsearchリクエスト。", "xpack.maps.source.esTopHitsSearch.sortFieldLabel": "並べ替えフィールド", "xpack.maps.source.esTopHitsSearch.sortOrderLabel": "並べ替え順", "xpack.maps.source.geofieldLabel": "地理空間フィールド", @@ -29996,7 +29964,6 @@ "xpack.osquery.updatePack.successToastMessageText": "正常に\"{packName}\"パックを更新しました", "xpack.osquery.viewSavedQuery.pageTitle": "\"{savedQueryId}\"詳細", "xpack.osquery.action_details.fetchError": "アクション詳細の取得中にエラーが発生しました", - "xpack.osquery.action_policy_details.fetchError": "ポリシー詳細の取得中にエラーが発生しました", "xpack.osquery.action_results.errorSearchDescription": "アクション結果検索でエラーが発生しました", "xpack.osquery.action_results.failSearchDescription": "アクション詳細を取得できませんでした", "xpack.osquery.action_results.fetchError": "アクション結果の取得中にエラーが発生しました", @@ -30017,7 +29984,6 @@ "xpack.osquery.addSavedQuery.form.saveQueryButtonLabel": "クエリを保存", "xpack.osquery.addSavedQuery.pageTitle": "保存されたクエリの追加", "xpack.osquery.addSavedQuery.viewSavedQueriesListTitle": "すべての保存されたクエリを表示", - "xpack.osquery.agent_groups.fetchError": "エージェントグループの取得中にエラーが発生しました", "xpack.osquery.agent_policies.fetchError": "エージェントポリシーの取得中にエラーが発生しました", "xpack.osquery.agent_policy_details.fetchError": "エージェントポリシー詳細の取得中にエラーが発生しました", "xpack.osquery.agent_status.fetchError": "エージェントステータスの取得中にエラーが発生しました", @@ -30677,7 +30643,6 @@ "xpack.reporting.diagnostic.browserMissingDependency": "システム依存関係が不足しているため、ブラウザーを正常に起動できませんでした。{url}を参照してください", "xpack.reporting.diagnostic.browserMissingFonts": "ブラウザーはデフォルトフォントを検索できませんでした。この問題を修正するには、{url}を参照してください。", "xpack.reporting.diagnostic.noUsableSandbox": "Chromiumサンドボックスを使用できません。これは「xpack.screenshotting.browser.chromium.disableSandbox」で無効にすることができます。この作業はご自身の責任で行ってください。{url}を参照してください", - "xpack.reporting.exportTypes.common.failedToDecryptReportJobDataErrorMessage": "レポートジョブデータの解読に失敗しました。{encryptionKey} が設定されていることを確認してこのレポートを再生成してください。{err}", "xpack.reporting.jobResponse.errorHandler.notAuthorized": "{jobtype}レポートを表示または削除する権限がありません", "xpack.reporting.jobsQuery.deleteError": "レポートを削除できません:{error}", "xpack.reporting.jobStatusDetail.attemptXofY": "{max_attempts}回中{attempts}回試行します。", @@ -30732,7 +30697,6 @@ "xpack.reporting.deprecations.reportingRoleUsers.manualStepThree": "[管理]>[セキュリティ]>[ロール]から、レポートのKibanaアプリケーション権限を付与する1つ以上のロールを作成します。", "xpack.reporting.deprecations.reportingRoleUsers.manualStepTwo": "存在する場合は、kibana.ymlで「xpack.reporting.roles.allow」を削除します。", "xpack.reporting.errorHandler.unknownError": "不明なエラー", - "xpack.reporting.exportTypes.common.missingJobHeadersErrorMessage": "ジョブヘッダーがありません", "xpack.reporting.jobCreatedBy.unknownUserPlaceholderText": "不明", "xpack.reporting.jobResponse.errorHandler.unknownError": "不明なエラー", "xpack.reporting.jobStatusDetail.deprecatedText": "これは廃止予定のエクスポートタイプです。将来のバージョンのKibanaとの互換性のためには、このレポートの自動化を再作成する必要があります。", @@ -35058,7 +35022,6 @@ "xpack.securitySolution.endpoint.policyNotFound": "ポリシーが見つかりません。", "xpack.securitySolution.endpoint.policyResponse.backLinkTitle": "エンドポイント詳細", "xpack.securitySolution.endpoint.policyResponse.title": "ポリシー応答", - "xpack.securitySolution.endpoint.protectionUpdates.automaticUpdates.enabled": "マニフェストは利用可能な最新バージョンに常に更新されます。更新を手動で管理する場合は、\"マニフェストを自動的に更新\"を無効にします。", "xpack.securitySolution.endpoint.protectionUpdates.automaticUpdates.enabledTitle": "自動更新が有効です", "xpack.securitySolution.endpoint.protectionUpdates.cancel": "キャンセル", "xpack.securitySolution.endpoint.protectionUpdates.deployedVersion.label": "現在デプロイされているバージョン", @@ -40463,9 +40426,7 @@ "xpack.transform.forceDeleteTransformMessage": "{count}{count, plural, other {変換}}の削除", "xpack.transform.managedTransformsWarningCallout": "{count, plural, other {これらの変換のうちの少なくとも1個の変換}}はElasticによってあらかじめ構成されています。{count, plural, other {それらを}}{action}すると、製品の他の部分に影響する可能性があります。", "xpack.transform.multiTransformActionsMenu.transformsCount": "{count}個の{count, plural, other {変換}}を選択済み", - "xpack.transform.stepCreateForm.createDataViewErrorMessage": "Kibanaデータビュー{dataViewName}の作成中にエラーが発生しました:", "xpack.transform.stepCreateForm.createTransformErrorMessage": "変換 {transformId} の取得中にエラーが発生しました。", - "xpack.transform.stepCreateForm.duplicateDataViewErrorMessage": "Kibanaデータビュー{dataViewName}の作成中にエラーが発生しました:データビューはすでに存在します。", "xpack.transform.stepDefineForm.invalidKuerySyntaxErrorMessageQueryBar": "無効なクエリ:{queryErrorMessage}", "xpack.transform.stepDefineForm.queryPlaceholderKql": "例: {example}.", "xpack.transform.stepDefineForm.queryPlaceholderLucene": "例: {example}.", @@ -43313,10 +43274,12 @@ "observabilityAlertDetails.alertThresholdTimeRangeRect.detailsTooltip": "しきい値", "randomSampling.ui.sliderControl.accuracyLabel": "精度", "randomSampling.ui.sliderControl.performanceLabel": "パフォーマンス", - "reactPackages.mountPointPortal.errorMessage": "ポータルコンテンツのレンダリングエラー", + "reporting.commonExportTypesHelpers.failedToDecryptReportJobDataErrorMessage": "レポートジョブデータの解読に失敗しました。{encryptionKey} が設定されていることを確認してこのレポートを再生成してください。{err}", + "reporting.commonExportTypesHelpers.missingJobHeadersErrorMessage": "ジョブヘッダーがありません", "reporting.common.browserCouldNotLaunchErrorMessage": "ブラウザーが起動していないため、スクリーンショットを生成できません。詳細については、サーバーログを参照してください。", "reporting.common.cloud.insufficientSystemMemoryError": "メモリ不足のため、このレポートを生成できません。", "reporting.common.pdfWorkerOutOfMemoryErrorMessage": "メモリ不足のため、PDFを生成できません。PDFのサイズを小さくして、このレポートを再試行してください。", + "reactPackages.mountPointPortal.errorMessage": "ポータルコンテンツのレンダリングエラー", "savedObjectsFinder.advancedSettings.listingLimitText": "一覧ページ用に取得するオブジェクトの数です", "savedObjectsFinder.advancedSettings.listingLimitTitle": "オブジェクト取得制限", "savedObjectsFinder.advancedSettings.perPageText": "読み込みダイアログで表示されるページごとのオブジェクトの数です", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index 617557d691e2c..192297f53e6ec 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -4951,7 +4951,6 @@ "management.settings.categoryNames.visualizationsLabel": "可视化", "management.settings.changeImageLinkText": "更改图片", "management.settings.customSettingTooltip": "定制设置", - "management.settings.field.codeEditorSyntaxErrorMessage": "JSON 语法无效", "management.settings.field.customSettingAriaLabel": "定制设置", "management.settings.field.imageChangeErrorMessage": "图片无法保存", "management.settings.field.invalidIconLabel": "无效", @@ -20109,17 +20108,7 @@ "xpack.indexLifecycleMgmt.hotPhase.maximumPrimaryShardDocsLabel": "主要分片中的最大文档数", "xpack.indexLifecycleMgmt.hotPhase.maximumPrimaryShardSizeLabel": "最大主分片大小", "xpack.indexLifecycleMgmt.hotPhase.rolloverFieldTitle": "滚动更新", - "xpack.indexLifecycleMgmt.indexLifecycleMgmtSummary.actionStatusTitle": "操作状态", - "xpack.indexLifecycleMgmt.indexLifecycleMgmtSummary.headers.currentActionHeader": "当前操作", - "xpack.indexLifecycleMgmt.indexLifecycleMgmtSummary.headers.currentActionTimeHeader": "当前操作名称", - "xpack.indexLifecycleMgmt.indexLifecycleMgmtSummary.headers.currentPhaseHeader": "当前阶段", - "xpack.indexLifecycleMgmt.indexLifecycleMgmtSummary.headers.failedStepHeader": "失败的步骤", - "xpack.indexLifecycleMgmt.indexLifecycleMgmtSummary.headers.lifecyclePolicyHeader": "生命周期策略", "xpack.indexLifecycleMgmt.indexLifecycleMgmtSummary.phaseDefinitionTitle": "阶段定义", - "xpack.indexLifecycleMgmt.indexLifecycleMgmtSummary.showPhaseDefinitionButton": "显示阶段定义", - "xpack.indexLifecycleMgmt.indexLifecycleMgmtSummary.showPhaseDefinitionDescriptionTitle": "阶段定义", - "xpack.indexLifecycleMgmt.indexLifecycleMgmtSummary.summaryErrorMessage": "索引生命周期错误", - "xpack.indexLifecycleMgmt.indexLifecycleMgmtSummary.summaryTitle": "索引生命周期管理", "xpack.indexLifecycleMgmt.indexManagementTable.addLifecyclePolicyConfirmModal.addPolicyButtonText": "添加策略", "xpack.indexLifecycleMgmt.indexManagementTable.addLifecyclePolicyConfirmModal.addPolicyToIndexError": "向索引添加策略时出错", "xpack.indexLifecycleMgmt.indexManagementTable.addLifecyclePolicyConfirmModal.cancelButtonText": "取消", @@ -23535,8 +23524,6 @@ "xpack.maps.blendedVectorLayer.clusteredLayerName": "集群 {displayName}", "xpack.maps.common.esSpatialRelation.clusterFilterLabel": "相交集群 {gridId}", "xpack.maps.deleteLayerConfirmModal.multiLayerWarning": "移除此图层还会移除 {numChildren} 个嵌套{numChildren, plural, other {图层}}。", - "xpack.maps.distanceSource.requestDescription": "获取指标的数据视图:{dataViewName}、地理空间字段:{geoFieldName}", - "xpack.maps.distanceSource.requestName": "距离联接请求内的 {leftSourceName}", "xpack.maps.embeddable.boundsFilterLabel": "地图边界内的 {geoFieldsLabel}", "xpack.maps.es_geo_utils.convert.unsupportedGeometryTypeErrorMessage": "无法将 {geometryType} 几何图形转换成 geojson,不支持", "xpack.maps.es_geo_utils.distanceFilterAlias": "{pointLabel} {distanceKm}km 内", @@ -23550,10 +23537,6 @@ "xpack.maps.esSearch.topHitsEntitiesCountMsg": "找到 {entityCount} 个实体。", "xpack.maps.esSearch.topHitsResultsTrimmedMsg": "结果限制为 ~{totalEntities} 个实体中的前 {entityCount} 个。", "xpack.maps.esSearch.topHitsSizeMsg": "显示每个实体排名前 {topHitsSize} 的文档。", - "xpack.maps.esSearchSource.requestDescription": "获取文档的数据视图:{dataViewName}、地理空间字段:{geoFieldName}", - "xpack.maps.esSearchSource.requestName": "{layerName} 文档请求", - "xpack.maps.esSearchSource.topHits.requestDescription": "获取最高命中结果的数据视图:{dataViewName}、实体:{entitiesFieldName}、地理空间字段:{geoFieldName}", - "xpack.maps.esSearchSource.topHits.requestName": "{layerName} 最高命中结果请求", "xpack.maps.fileUpload.trimmedResultsMsg": "结果仅限于 {numFeatures} 个特征、{previewCoverage}% 的文件。", "xpack.maps.filterByMapExtentMenuItem.displayName": "按地图边界筛选 {containerLabel}", "xpack.maps.filterByMapExtentMenuItem.displayNameTooltip": "当您缩放和平移地图时,{containerLabel} 会进行更新以仅显示在地图边界中可见的数据。", @@ -23576,7 +23559,6 @@ "xpack.maps.mask.maskLabel": "隐藏 {hideNoun}", "xpack.maps.mask.whenJoinMetric": "{whenLabel} 联接指标", "xpack.maps.maskLegend.is": "{aggLabel} 为", - "xpack.maps.pewPew.requestName": "{layerName} 路径请求", "xpack.maps.scalingDocs.clustersDetails": "结果超过 {maxResultWindow} 个文档时显示集群。结果数小于 {maxResultWindow} 时显示文档。", "xpack.maps.scalingDocs.limitDetails": "显示前 {maxResultWindow} 个文档中的特征。", "xpack.maps.scalingDocs.maxResultWindow": "{link} 索引设置提供的 {maxResultWindow} 限制。", @@ -23592,15 +23574,8 @@ "xpack.maps.source.emsTileSourceDescription": "来自 {host} 的基础地图服务", "xpack.maps.source.esAggSource.topTermLabel": "排名靠前 {fieldLabel}", "xpack.maps.source.esGeoGrid.groupBy.termsDescription": "为排名前 {maxTermsTracks} 的词创建轨迹。点数超出限制时,会截短轨迹。", - "xpack.maps.source.esGeoLine.entityRequestDescription": "获取地图缓冲内实体的数据视图:{dataViewName}、实体:{splitFieldName}", - "xpack.maps.source.esGeoLine.timeSeriesTrackRequestDescription": "获取轨迹的数据视图:{dataViewName}、地理空间字段:{geoFieldName}", - "xpack.maps.source.esGeoLine.trackRequestDescription": "获取 {numEntities} 个实体的轨迹的数据视图:{dataViewName}、地理空间字段:{geoFieldName}", "xpack.maps.source.esGeoLineDisabledReason": "{title} 需要黄金级许可证。", - "xpack.maps.source.esGrid.compositeInspector.requestName": "{layerName} {bucketsName} 组合请求 ({requestCount})", - "xpack.maps.source.esGrid.compositeInspectorDescription": "获取 {bucketsName} 的数据视图:{dataViewName}、地理空间字段:{geoFieldName}", "xpack.maps.source.esGrid.compositePaginationErrorMessage": "{layerName} 正导致过多的请求。降低“网格分辨率”和/或减少热门词“指标”的数量。", - "xpack.maps.source.esGrid.inspector.requestDescription": "获取 {bucketsName} 的数据视图:{dataViewName}、地理空间字段:{geoFieldName}", - "xpack.maps.source.esGrid.inspector.requestName": "{layerName} {bucketsName} 请求", "xpack.maps.source.esGrid.resolutionParamErrorMessage": "无法识别网格分辨率参数:{resolution}", "xpack.maps.source.esJoin.countLabel": "{indexPatternLabel} 的计数", "xpack.maps.source.esSearch.clusterScalingLabel": "结果超过 {maxResultWindow} 个时显示集群", @@ -23609,18 +23584,14 @@ "xpack.maps.source.esSearch.loadTooltipPropertiesErrorMsg": "找不到文档,_id:{docId}", "xpack.maps.source.esSearch.mvtScalingJoinMsg": "矢量磁贴支持一个词联接。您的图层具有 {numberOfJoins} 个联接。切换到矢量磁贴会保留第一个词联接,并从图层配置中移除所有其他联接。", "xpack.maps.source.esSource.noGeoFieldErrorMessage": "数据视图“{indexPatternLabel}”不再包含地理字段“{geoField}”", - "xpack.maps.source.esSource.requestFailedErrorMessage": "Elasticsearch 搜索请求失败,错误:{message}", "xpack.maps.source.esSource.stylePropsMetaRequestName": "{layerName} - 元数据", "xpack.maps.source.MVTSingleLayerVectorSourceEditor.urlHelpMessage": ".mvt 矢量磁帖服务的 URL。例如 {url}", - "xpack.maps.source.pewPew.inspectorDescription": "获取路径的数据视图:{dataViewName}、源:{sourceFieldName}、目标:{destFieldName}", "xpack.maps.spatialJoin.wizardForm.withinExpressionValue": "图层特征的 {distance} {units}", "xpack.maps.spatialJoinExpression.noDataViewTitle": "无法加载数据视图 {dataViewId}。", "xpack.maps.spatialJoinExpression.value": "{geoField} 中的特征", "xpack.maps.style.fieldSelect.OriginLabel": "来自 {fieldOrigin} 的字段", "xpack.maps.termJoinExpression.topTerms": "排名靠前 {size}", "xpack.maps.termJoinExpression.value": "来自 {term} 的 {topTerms} 词", - "xpack.maps.termSource.requestDescription": "获取指标的数据视图:{dataViewName}、词字段:{termFieldName}", - "xpack.maps.termSource.requestName": "{leftSourceName} 词联接请求", "xpack.maps.tiles.resultsCompleteMsg": "找到 {countPrefix}{count} 个文档。", "xpack.maps.tiles.resultsTrimmedMsg": "结果仅限为 {countPrefix}{count} 个文档。", "xpack.maps.tooltip.pageNumerText": "{total} 的 {pageNumber}", @@ -24060,8 +24031,6 @@ "xpack.maps.source.esGeoLine.sortFieldPlaceholder": "选择排序字段", "xpack.maps.source.esGeoLine.splitFieldLabel": "实体", "xpack.maps.source.esGeoLine.splitFieldPlaceholder": "选择实体字段", - "xpack.maps.source.esGeoLine.timeSeriesTrackRequestName": "“{layerName}”轨迹请求(时间序列)", - "xpack.maps.source.esGeoLine.trackRequestName": "“{layerName}”轨迹请求(词)", "xpack.maps.source.esGeoLine.trackSettingsLabel": "轨迹", "xpack.maps.source.esGeoLineDescription": "从点创建线", "xpack.maps.source.esGeoLineTitle": "轨迹", @@ -24104,7 +24073,6 @@ "xpack.maps.source.esSearch.useMVTVectorTiles": "使用矢量磁贴", "xpack.maps.source.esSearchDescription": "Elasticsearch 的点、线和多边形", "xpack.maps.source.esSearchTitle": "文档", - "xpack.maps.source.esSource.stylePropsMetaRequestDescription": "检索用于计算符号化带的字段元数据的 Elasticsearch 请求。", "xpack.maps.source.esTopHitsSearch.sortFieldLabel": "排序字段", "xpack.maps.source.esTopHitsSearch.sortOrderLabel": "排序顺序", "xpack.maps.source.geofieldLabel": "地理空间字段", @@ -29994,7 +29962,6 @@ "xpack.osquery.updatePack.successToastMessageText": "已成功更新“{packName}”包", "xpack.osquery.viewSavedQuery.pageTitle": "“{savedQueryId}”详情", "xpack.osquery.action_details.fetchError": "提取操作详情时出错", - "xpack.osquery.action_policy_details.fetchError": "提取策略详情时出错", "xpack.osquery.action_results.errorSearchDescription": "搜索操作结果时发生错误", "xpack.osquery.action_results.failSearchDescription": "无法获取操作结果", "xpack.osquery.action_results.fetchError": "提取操作结果时出错", @@ -30015,7 +29982,6 @@ "xpack.osquery.addSavedQuery.form.saveQueryButtonLabel": "保存查询", "xpack.osquery.addSavedQuery.pageTitle": "添加已保存查询", "xpack.osquery.addSavedQuery.viewSavedQueriesListTitle": "查看所有已保存查询", - "xpack.osquery.agent_groups.fetchError": "提取代理组时出错", "xpack.osquery.agent_policies.fetchError": "提取代理策略时出错", "xpack.osquery.agent_policy_details.fetchError": "提取代理策略详情时出错", "xpack.osquery.agent_status.fetchError": "提取代理状态时出错", @@ -30675,7 +30641,6 @@ "xpack.reporting.diagnostic.browserMissingDependency": "由于缺少系统依赖项,浏览器无法正常启动。请参见 {url}", "xpack.reporting.diagnostic.browserMissingFonts": "浏览器找不到默认字体。请参见 {url} 以解决此问题。", "xpack.reporting.diagnostic.noUsableSandbox": "无法使用 Chromium 沙盒。您自行承担使用“xpack.screenshotting.browser.chromium.disableSandbox”禁用此项的风险。请参见 {url}", - "xpack.reporting.exportTypes.common.failedToDecryptReportJobDataErrorMessage": "无法解密报告作业数据。请确保已设置 {encryptionKey},然后重新生成此报告。{err}", "xpack.reporting.jobResponse.errorHandler.notAuthorized": "抱歉,您无权查看或删除 {jobtype} 报告", "xpack.reporting.jobsQuery.deleteError": "无法删除报告:{error}", "xpack.reporting.jobStatusDetail.attemptXofY": "尝试 {attempts} 次,最多可尝试 {max_attempts} 次。", @@ -30730,7 +30695,6 @@ "xpack.reporting.deprecations.reportingRoleUsers.manualStepThree": "前往“管理”>“安全性”>“角色”以创建一个或多个针对 Reporting 授予 Kibana 应用程序权限的角色。", "xpack.reporting.deprecations.reportingRoleUsers.manualStepTwo": "移除 kibana.yml 中的“xpack.reporting.roles.allow”(如果存在)。", "xpack.reporting.errorHandler.unknownError": "未知错误", - "xpack.reporting.exportTypes.common.missingJobHeadersErrorMessage": "作业标头缺失", "xpack.reporting.jobCreatedBy.unknownUserPlaceholderText": "未知", "xpack.reporting.jobResponse.errorHandler.unknownError": "未知错误", "xpack.reporting.jobStatusDetail.deprecatedText": "这是已弃用的导出类型。此报告的自动化将需要重新创建,才能与未来版本的 Kibana 兼容。", @@ -35054,7 +35018,6 @@ "xpack.securitySolution.endpoint.policyNotFound": "未找到策略!", "xpack.securitySolution.endpoint.policyResponse.backLinkTitle": "终端详情", "xpack.securitySolution.endpoint.policyResponse.title": "策略响应", - "xpack.securitySolution.endpoint.protectionUpdates.automaticUpdates.enabled": "会始终将清单更新到可用的最新版本。如果不想手动控制更新,请禁用“自动更新清单”。", "xpack.securitySolution.endpoint.protectionUpdates.automaticUpdates.enabledTitle": "已启用自动更新", "xpack.securitySolution.endpoint.protectionUpdates.cancel": "取消", "xpack.securitySolution.endpoint.protectionUpdates.deployedVersion.label": "当前部署的版本", @@ -40457,9 +40420,7 @@ "xpack.transform.forceDeleteTransformMessage": "删除 {count} {count, plural, other {转换}}", "xpack.transform.managedTransformsWarningCallout": "{count, plural, other {至少一个此类转换}}由 Elastic 预配置;{action} {count, plural, other {这些转换}}可能会影响该产品的其他部分。", "xpack.transform.multiTransformActionsMenu.transformsCount": "已选定 {count} 个{count, plural, other {转换}}", - "xpack.transform.stepCreateForm.createDataViewErrorMessage": "创建 Kibana 数据视图 {dataViewName} 时发生错误:", "xpack.transform.stepCreateForm.createTransformErrorMessage": "创建转换 {transformId} 时出错:", - "xpack.transform.stepCreateForm.duplicateDataViewErrorMessage": "创建 Kibana 数据视图 {dataViewName} 时发生错误:数据视图已存在。", "xpack.transform.stepDefineForm.invalidKuerySyntaxErrorMessageQueryBar": "无效查询:{queryErrorMessage}", "xpack.transform.stepDefineForm.queryPlaceholderKql": "例如,{example}", "xpack.transform.stepDefineForm.queryPlaceholderLucene": "例如,{example}", @@ -43307,10 +43268,12 @@ "observabilityAlertDetails.alertThresholdTimeRangeRect.detailsTooltip": "阈值", "randomSampling.ui.sliderControl.accuracyLabel": "准确性", "randomSampling.ui.sliderControl.performanceLabel": "性能", - "reactPackages.mountPointPortal.errorMessage": "呈现门户内容时出错", + "reporting.commonExportTypesHelpers.missingJobHeadersErrorMessage": "作业标头缺失", + "reporting.commonExportTypesHelpers.failedToDecryptReportJobDataErrorMessage": "无法解密报告作业数据。请确保已设置 {encryptionKey},然后重新生成此报告。{err}", "reporting.common.browserCouldNotLaunchErrorMessage": "无法生成屏幕截图,因为浏览器未启动。有关更多信息,请查看服务器日志。", "reporting.common.cloud.insufficientSystemMemoryError": "由于内存不足,无法生成此报告。", "reporting.common.pdfWorkerOutOfMemoryErrorMessage": "由于内存不足,无法生成 PDF。尝试生成更小的 PDF,然后重试此报告。", + "reactPackages.mountPointPortal.errorMessage": "呈现门户内容时出错", "savedObjectsFinder.advancedSettings.listingLimitText": "要为列表页面提取的对象数目", "savedObjectsFinder.advancedSettings.listingLimitTitle": "对象列表限制", "savedObjectsFinder.advancedSettings.perPageText": "加载对话框中每页要显示的对象数目", diff --git a/x-pack/plugins/triggers_actions_ui/common/experimental_features.ts b/x-pack/plugins/triggers_actions_ui/common/experimental_features.ts index 501d9b7f22239..066487d5af6a4 100644 --- a/x-pack/plugins/triggers_actions_ui/common/experimental_features.ts +++ b/x-pack/plugins/triggers_actions_ui/common/experimental_features.ts @@ -19,6 +19,8 @@ export const allowedExperimentalValues = Object.freeze({ rulesDetailLogs: true, ruleUseExecutionStatus: false, ruleKqlBar: false, + isMustacheAutocompleteOn: false, + showMustacheAutocompleteSwitch: false, }); type ExperimentalConfigKeys = Array; @@ -29,7 +31,8 @@ const allowedKeys = Object.keys(allowedExperimentalValues) as Readonly void; @@ -291,7 +291,6 @@ export const TextAreaWithAutocomplete: React.FunctionComponent closeList(), [closeList]); - const onScroll = useCallback( (evt) => { // FUTURE ENGINEER -> we need to make sure to not close the autocomplete option list diff --git a/x-pack/plugins/stack_connectors/public/lib/filter_suggestions_for_autocomplete.test.ts b/x-pack/plugins/triggers_actions_ui/public/application/components/text_area_with_autocomplete/lib/filter_suggestions_for_autocomplete.test.ts similarity index 100% rename from x-pack/plugins/stack_connectors/public/lib/filter_suggestions_for_autocomplete.test.ts rename to x-pack/plugins/triggers_actions_ui/public/application/components/text_area_with_autocomplete/lib/filter_suggestions_for_autocomplete.test.ts diff --git a/x-pack/plugins/stack_connectors/public/lib/filter_suggestions_for_autocomplete.ts b/x-pack/plugins/triggers_actions_ui/public/application/components/text_area_with_autocomplete/lib/filter_suggestions_for_autocomplete.ts similarity index 100% rename from x-pack/plugins/stack_connectors/public/lib/filter_suggestions_for_autocomplete.ts rename to x-pack/plugins/triggers_actions_ui/public/application/components/text_area_with_autocomplete/lib/filter_suggestions_for_autocomplete.ts diff --git a/x-pack/plugins/stack_connectors/public/lib/template_action_variable.test.ts b/x-pack/plugins/triggers_actions_ui/public/application/components/text_area_with_autocomplete/lib/template_action_variable.test.ts similarity index 100% rename from x-pack/plugins/stack_connectors/public/lib/template_action_variable.test.ts rename to x-pack/plugins/triggers_actions_ui/public/application/components/text_area_with_autocomplete/lib/template_action_variable.test.ts diff --git a/x-pack/plugins/stack_connectors/public/lib/template_action_variable.ts b/x-pack/plugins/triggers_actions_ui/public/application/components/text_area_with_autocomplete/lib/template_action_variable.ts similarity index 100% rename from x-pack/plugins/stack_connectors/public/lib/template_action_variable.ts rename to x-pack/plugins/triggers_actions_ui/public/application/components/text_area_with_autocomplete/lib/template_action_variable.ts diff --git a/x-pack/plugins/triggers_actions_ui/public/application/components/text_area_with_message_variables.tsx b/x-pack/plugins/triggers_actions_ui/public/application/components/text_area_with_message_variables.tsx index c19ac416b4695..e666082638ea7 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/components/text_area_with_message_variables.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/components/text_area_with_message_variables.tsx @@ -9,6 +9,8 @@ import React, { useState } from 'react'; import { EuiTextArea, EuiFormRow } from '@elastic/eui'; import { ActionVariable } from '@kbn/alerting-plugin/common'; import { AddMessageVariables } from '@kbn/alerts-ui-shared'; +import { getIsExperimentalFeatureEnabled } from '../../common/get_experimental_features'; +import { TextAreaWithAutocomplete } from './text_area_with_autocomplete'; import { templateActionVariable } from '../lib'; interface Props { @@ -23,7 +25,7 @@ interface Props { errors?: string[]; } -export const TextAreaWithMessageVariables: React.FunctionComponent = ({ +const TextAreaWithMessageVariablesLegacy: React.FunctionComponent = ({ messageVariables, paramsProperty, index, @@ -87,3 +89,15 @@ export const TextAreaWithMessageVariables: React.FunctionComponent = ({ ); }; + +export const TextAreaWithMessageVariables = (props: Props) => { + let isMustacheAutocompleteOn; + try { + isMustacheAutocompleteOn = getIsExperimentalFeatureEnabled('isMustacheAutocompleteOn'); + } catch (e) { + isMustacheAutocompleteOn = false; + } + + if (isMustacheAutocompleteOn) return TextAreaWithAutocomplete(props); + return TextAreaWithMessageVariablesLegacy(props); +}; diff --git a/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_rule_aad_template_fields.ts b/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_rule_aad_template_fields.ts new file mode 100644 index 0000000000000..99be4c4b118b8 --- /dev/null +++ b/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_rule_aad_template_fields.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 type { HttpStart } from '@kbn/core-http-browser'; +import { DataViewField } from '@kbn/data-views-plugin/common'; +import { BASE_RAC_ALERTS_API_PATH } from '@kbn/rule-registry-plugin/common'; +import { ActionVariable } from '@kbn/alerting-plugin/common'; +import { useEffect, useMemo, useState } from 'react'; +import { EcsFlat } from '@kbn/ecs'; +import { EcsMetadata } from '@kbn/alerts-as-data-utils/src/field_maps/types'; +import { isEmpty } from 'lodash'; + +export const getDescription = (fieldName: string, ecsFlat: Record) => { + let ecsField = ecsFlat[fieldName]; + if (isEmpty(ecsField?.description ?? '') && fieldName.includes('kibana.alert.')) { + ecsField = ecsFlat[fieldName.replace('kibana.alert.', '')]; + } + return ecsField?.description ?? ''; +}; + +async function loadRuleTypeAadTemplateFields({ + http, + ruleTypeId, +}: { + http: HttpStart; + ruleTypeId: string; +}): Promise { + if (!ruleTypeId || !http) return []; + const fields = await http.get(`${BASE_RAC_ALERTS_API_PATH}/aad_fields`, { + query: { ruleTypeId }, + }); + + return fields; +} + +export function useRuleTypeAadTemplateFields( + http: HttpStart, + ruleTypeId: string | undefined, + enabled: boolean +): { isLoading: boolean; fields: ActionVariable[] } { + // Reimplement useQuery here; this hook is sometimes called in contexts without a QueryClientProvider + const [isLoading, setIsLoading] = useState(false); + const [data, setData] = useState([]); + + useEffect(() => { + if (enabled && data.length === 0 && ruleTypeId) { + setIsLoading(true); + loadRuleTypeAadTemplateFields({ http, ruleTypeId }).then((res) => { + setData(res); + setIsLoading(false); + }); + } + }, [data, enabled, http, ruleTypeId]); + + return useMemo( + () => ({ + isLoading, + fields: data.map((d) => ({ + name: d.name, + description: getDescription(d.name, EcsFlat), + })), + }), + [data, isLoading] + ); +} diff --git a/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/clone.test.ts b/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/clone.test.ts index 54e987d18c917..cc9b1ddab0218 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/clone.test.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/clone.test.ts @@ -75,6 +75,7 @@ describe('cloneRule', () => { "level": "info", "message": "alert ", }, + "useAlertDataForTemplate": undefined, "uuid": "123456", }, ], diff --git a/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/common_transformations.ts b/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/common_transformations.ts index e659cfbdfe4bd..da0cd8419e078 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/common_transformations.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/common_transformations.ts @@ -16,11 +16,13 @@ const transformAction: RewriteRequestCase = ({ params, frequency, alerts_filter: alertsFilter, + use_alert_data_for_template: useAlertDataForTemplate, }) => ({ group, id, params, actionTypeId, + useAlertDataForTemplate, ...(frequency ? { frequency: { diff --git a/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/create.ts b/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/create.ts index d8b8c85ad26a5..a2ab9c5b4dc3c 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/create.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/create.ts @@ -27,17 +27,20 @@ const rewriteBodyRequest: RewriteResponseCase = ({ }): any => ({ ...res, rule_type_id: ruleTypeId, - actions: actions.map(({ group, id, params, frequency, alertsFilter }) => ({ - group, - id, - params, - frequency: { - notify_when: frequency!.notifyWhen, - throttle: frequency!.throttle, - summary: frequency!.summary, - }, - alerts_filter: alertsFilter, - })), + actions: actions.map( + ({ group, id, params, frequency, alertsFilter, useAlertDataForTemplate }) => ({ + group, + id, + params, + frequency: { + notify_when: frequency!.notifyWhen, + throttle: frequency!.throttle, + summary: frequency!.summary, + }, + alerts_filter: alertsFilter, + use_alert_data_for_template: useAlertDataForTemplate, + }) + ), }); export async function createRule({ diff --git a/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/update.ts b/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/update.ts index ee2418d22262b..0d6371cfa1fdb 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/update.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/update.ts @@ -17,18 +17,21 @@ type RuleUpdatesBody = Pick< >; const rewriteBodyRequest: RewriteResponseCase = ({ actions, ...res }): any => ({ ...res, - actions: actions.map(({ group, id, params, frequency, uuid, alertsFilter }) => ({ - group, - id, - params, - frequency: { - notify_when: frequency!.notifyWhen, - throttle: frequency!.throttle, - summary: frequency!.summary, - }, - alerts_filter: alertsFilter, - ...(uuid && { uuid }), - })), + actions: actions.map( + ({ group, id, params, frequency, uuid, alertsFilter, useAlertDataForTemplate }) => ({ + group, + id, + params, + frequency: { + notify_when: frequency!.notifyWhen, + throttle: frequency!.throttle, + summary: frequency!.summary, + }, + alerts_filter: alertsFilter, + use_alert_data_for_template: useAlertDataForTemplate, + ...(uuid && { uuid }), + }) + ), }); export async function updateRule({ diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/action_form.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/action_form.tsx index d515cd9510cc6..6d91e1837b830 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/action_form.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/action_form.tsx @@ -60,6 +60,7 @@ export interface ActionAccordionFormProps { defaultActionMessage?: string; setActionIdByIndex: (id: string, index: number) => void; setActionGroupIdByIndex?: (group: string, index: number) => void; + setActionUseAlertDataForTemplate?: (enabled: boolean, index: number) => void; setActions: (actions: RuleAction[]) => void; setActionParamsProperty: (key: string, value: RuleActionParam, index: number) => void; setActionFrequencyProperty: (key: string, value: RuleActionParam, index: number) => void; @@ -70,6 +71,7 @@ export interface ActionAccordionFormProps { ) => void; featureId: string; producerId: string; + ruleTypeId?: string; messageVariables?: ActionVariables; summaryMessageVariables?: ActionVariables; setHasActionsDisabled?: (value: boolean) => void; @@ -84,7 +86,6 @@ export interface ActionAccordionFormProps { minimumThrottleInterval?: [number | undefined, string]; notifyWhenSelectOptions?: NotifyWhenSelectOptions[]; defaultRuleFrequency?: RuleActionFrequency; - ruleTypeId?: string; hasFieldsForAAD?: boolean; disableErrorMessages?: boolean; } @@ -99,6 +100,7 @@ export const ActionForm = ({ defaultActionGroupId, setActionIdByIndex, setActionGroupIdByIndex, + setActionUseAlertDataForTemplate, setActions, setActionParamsProperty, setActionFrequencyProperty, @@ -437,6 +439,7 @@ export const ActionForm = ({ actionConnector={actionConnector} index={index} key={`action-form-action-at-${actionItem.uuid}`} + setActionUseAlertDataForTemplate={setActionUseAlertDataForTemplate} setActionParamsProperty={setActionParamsProperty} setActionFrequencyProperty={setActionFrequencyProperty} setActionAlertsFilterProperty={setActionAlertsFilterProperty} diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/action_type_form.test.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/action_type_form.test.tsx index cc0594b365b9e..8b774325af985 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/action_type_form.test.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/action_type_form.test.tsx @@ -64,6 +64,19 @@ jest.mock('@kbn/kibana-react-plugin/public/ui_settings/use_ui_setting', () => ({ useUiSetting: jest.fn().mockImplementation((_, defaultValue) => defaultValue), })); +jest.mock('../../../common/get_experimental_features', () => ({ + getIsExperimentalFeatureEnabled() { + return true; + }, +})); + +jest.mock('../../hooks/use_rule_aad_template_fields', () => ({ + useRuleTypeAadTemplateFields: () => ({ + isLoading: false, + fields: [], + }), +})); + describe('action_type_form', () => { afterEach(() => { jest.clearAllMocks(); @@ -402,6 +415,59 @@ describe('action_type_form', () => { ]); }); + it('clears the default message when the user toggles the "Use template fields from alerts index" switch ', async () => { + const setActionParamsProperty = jest.fn(); + const actionType = actionTypeRegistryMock.createMockActionTypeModel({ + id: '.pagerduty', + iconClass: 'test', + selectMessage: 'test', + validateParams: (): Promise> => { + const validationResult = { errors: {} }; + return Promise.resolve(validationResult); + }, + actionConnectorFields: null, + actionParamsFields: mockedActionParamsFields, + defaultActionParams: { + dedupKey: '{{rule.id}}:{{alert.id}}', + eventAction: 'resolve', + }, + }); + actionTypeRegistry.get.mockReturnValue(actionType); + + const wrapper = render( + + {getActionTypeForm({ + index: 1, + ruleTypeId: 'test', + setActionParamsProperty, + actionItem: { + id: '123', + actionTypeId: '.pagerduty', + group: 'recovered', + params: { + eventAction: 'recovered', + dedupKey: '232323', + summary: '2323', + source: 'source', + severity: '1', + timestamp: new Date().toISOString(), + component: 'test', + group: 'group', + class: 'test class', + }, + }, + })} + + ); + + expect(wrapper.getByTestId('mustacheAutocompleteSwitch')).toBeTruthy(); + + await act(async () => { + wrapper.getByTestId('mustacheAutocompleteSwitch').click(); + }); + expect(setActionParamsProperty).toHaveBeenCalledWith('dedupKey', '', 1); + }); + describe('Customize notify when options', () => { it('should not have "On status changes" notify when option for summary actions', async () => { const actionType = actionTypeRegistryMock.createMockActionTypeModel({ @@ -523,6 +589,7 @@ function getActionTypeForm({ onAddConnector, onDeleteAction, onConnectorSelected, + setActionParamsProperty, setActionFrequencyProperty, setActionAlertsFilterProperty, hasAlertsMappings = true, @@ -530,6 +597,7 @@ function getActionTypeForm({ summaryMessageVariables = { context: [], state: [], params: [] }, notifyWhenSelectOptions, defaultNotifyWhenValue, + ruleTypeId, }: { index?: number; actionConnector?: ActionConnector, Record>; @@ -541,12 +609,14 @@ function getActionTypeForm({ onDeleteAction?: () => void; onConnectorSelected?: (id: string) => void; setActionFrequencyProperty?: () => void; + setActionParamsProperty?: () => void; setActionAlertsFilterProperty?: () => void; hasAlertsMappings?: boolean; messageVariables?: ActionVariables; summaryMessageVariables?: ActionVariables; notifyWhenSelectOptions?: NotifyWhenSelectOptions[]; defaultNotifyWhenValue?: RuleNotifyWhenType; + ruleTypeId?: string; }) { const actionConnectorDefault = { actionTypeId: '.pagerduty', @@ -628,7 +698,7 @@ function getActionTypeForm({ onDeleteAction={onDeleteAction ?? jest.fn()} onConnectorSelected={onConnectorSelected ?? jest.fn()} defaultActionGroupId={defaultActionGroupId ?? 'default'} - setActionParamsProperty={jest.fn()} + setActionParamsProperty={setActionParamsProperty ?? jest.fn()} setActionFrequencyProperty={setActionFrequencyProperty ?? jest.fn()} setActionAlertsFilterProperty={setActionAlertsFilterProperty ?? jest.fn()} index={index ?? 1} @@ -641,6 +711,7 @@ function getActionTypeForm({ defaultNotifyWhenValue={defaultNotifyWhenValue} producerId="infrastructure" featureId="infrastructure" + ruleTypeId={ruleTypeId} /> ); } diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/action_type_form.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/action_type_form.tsx index 3f0982b1b24f3..83ad089c8e691 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/action_type_form.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/action_type_form.tsx @@ -29,6 +29,7 @@ import { EuiSplitPanel, useEuiTheme, EuiCallOut, + EuiSwitch, } from '@elastic/eui'; import { isEmpty, partition, some } from 'lodash'; import { @@ -42,6 +43,8 @@ import { getDurationUnitValue, parseDuration, } from '@kbn/alerting-plugin/common/parse_duration'; +import { SavedObjectAttribute } from '@kbn/core-saved-objects-api-server'; +import { getIsExperimentalFeatureEnabled } from '../../../common/get_experimental_features'; import { betaBadgeProps } from './beta_badge_props'; import { IErrorObject, @@ -64,6 +67,7 @@ import { validateParamsForWarnings } from '../../lib/validate_params_for_warning import { ActionAlertsFilterTimeframe } from './action_alerts_filter_timeframe'; import { ActionAlertsFilterQuery } from './action_alerts_filter_query'; import { validateActionFilterQuery } from '../../lib/value_validators'; +import { useRuleTypeAadTemplateFields } from '../../hooks/use_rule_aad_template_fields'; export type ActionTypeFormProps = { actionItem: RuleAction; @@ -72,6 +76,7 @@ export type ActionTypeFormProps = { onAddConnector: () => void; onConnectorSelected: (id: string) => void; onDeleteAction: () => void; + setActionUseAlertDataForTemplate?: (enabled: boolean, index: number) => void; setActionParamsProperty: (key: string, value: RuleActionParam, index: number) => void; setActionFrequencyProperty: (key: string, value: RuleActionParam, index: number) => void; setActionAlertsFilterProperty: ( @@ -120,6 +125,7 @@ export const ActionTypeForm = ({ onAddConnector, onConnectorSelected, onDeleteAction, + setActionUseAlertDataForTemplate, setActionParamsProperty, setActionFrequencyProperty, setActionAlertsFilterProperty, @@ -148,7 +154,7 @@ export const ActionTypeForm = ({ }: ActionTypeFormProps) => { const { application: { capabilities }, - http: { basePath }, + http, } = useKibana().services; const { euiTheme } = useEuiTheme(); const [isOpen, setIsOpen] = useState(true); @@ -178,6 +184,53 @@ export const ActionTypeForm = ({ const isSummaryAction = actionItem.frequency?.summary; + const [useAadTemplateFields, setUseAadTemplateField] = useState( + actionItem?.useAlertDataForTemplate ?? false + ); + const [storedActionParamsForAadToggle, setStoredActionParamsForAadToggle] = useState< + Record + >({}); + + const { fields: aadTemplateFields } = useRuleTypeAadTemplateFields( + http, + ruleTypeId, + useAadTemplateFields + ); + + const templateFields = useMemo( + () => (useAadTemplateFields ? aadTemplateFields : availableActionVariables), + [aadTemplateFields, availableActionVariables, useAadTemplateFields] + ); + + let showMustacheAutocompleteSwitch; + try { + showMustacheAutocompleteSwitch = + getIsExperimentalFeatureEnabled('showMustacheAutocompleteSwitch') && ruleTypeId; + } catch (e) { + showMustacheAutocompleteSwitch = false; + } + + const handleUseAadTemplateFields = useCallback(() => { + setUseAadTemplateField((prevVal) => { + if (setActionUseAlertDataForTemplate) { + setActionUseAlertDataForTemplate(!prevVal, index); + } + return !prevVal; + }); + const currentActionParams = { ...actionItem.params }; + for (const key of Object.keys(currentActionParams)) { + setActionParamsProperty(key, storedActionParamsForAadToggle[key] ?? '', index); + } + setStoredActionParamsForAadToggle(currentActionParams); + }, [ + setActionUseAlertDataForTemplate, + storedActionParamsForAadToggle, + setStoredActionParamsForAadToggle, + setActionParamsProperty, + actionItem.params, + index, + ]); + const getDefaultParams = async () => { const connectorType = await actionTypeRegistry.get(actionItem.actionTypeId); let defaultParams; @@ -227,9 +280,15 @@ export const ActionTypeForm = ({ const defaultParams = await getDefaultParams(); if (defaultParams) { for (const [key, paramValue] of Object.entries(defaultParams)) { + const defaultAADParams: typeof defaultParams = {}; if (actionItem.params[key] === undefined || actionItem.params[key] === null) { setActionParamsProperty(key, paramValue, index); + // Add default param to AAD defaults only if it does not contain any template code + if (typeof paramValue !== 'string' || !paramValue.match(/{{.*?}}/g)) { + defaultAADParams[key] = paramValue; + } } + setStoredActionParamsForAadToggle(defaultAADParams); } } })(); @@ -240,9 +299,14 @@ export const ActionTypeForm = ({ (async () => { const defaultParams = await getDefaultParams(); if (defaultParams && actionGroup) { + const defaultAADParams: typeof defaultParams = {}; for (const [key, paramValue] of Object.entries(defaultParams)) { setActionParamsProperty(key, paramValue, index); + if (!paramValue.match(/{{.*?}}/g)) { + defaultAADParams[key] = paramValue; + } } + setStoredActionParamsForAadToggle(defaultAADParams); } })(); // eslint-disable-next-line react-hooks/exhaustive-deps @@ -273,6 +337,12 @@ export const ActionTypeForm = ({ })(); }, [actionItem, disableErrorMessages]); + useEffect(() => { + if (isEmpty(storedActionParamsForAadToggle) && actionItem.params.subAction) { + setStoredActionParamsForAadToggle(actionItem.params); + } + }, [actionItem.params, storedActionParamsForAadToggle]); + const canSave = hasSaveActionsCapability(capabilities); const actionGroupDisplay = ( @@ -463,39 +533,54 @@ export const ActionTypeForm = ({ {ParamsFieldsComponent ? ( - - { - setWarning( - validateParamsForWarnings( - value, - basePath.publicBaseUrl, - availableActionVariables - ) - ); - setActionParamsProperty(key, value, i); - }} - messageVariables={availableActionVariables} - defaultMessage={ - // if action is a summary action, show the default summary message - isSummaryAction - ? defaultSummaryMessage - : selectedActionGroup?.defaultActionMessage ?? defaultActionMessage - } - useDefaultMessage={useDefaultMessage} - actionConnector={actionConnector} - executionMode={ActionConnectorMode.ActionForm} - /> - {warning ? ( - <> - - - - ) : null} - + + {showMustacheAutocompleteSwitch && ( + + + + )} + + + { + setWarning( + validateParamsForWarnings( + value, + http.basePath.publicBaseUrl, + availableActionVariables + ) + ); + setActionParamsProperty(key, value, i); + }} + messageVariables={templateFields} + defaultMessage={ + // if action is a summary action, show the default summary message + isSummaryAction + ? defaultSummaryMessage + : selectedActionGroup?.defaultActionMessage ?? defaultActionMessage + } + useDefaultMessage={useDefaultMessage} + actionConnector={actionConnector} + executionMode={ActionConnectorMode.ActionForm} + ruleTypeId={ruleTypeId} + /> + {warning ? ( + <> + + + + ) : null} + + + ) : null} diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_form/rule_form.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_form/rule_form.tsx index c88e3beba0cad..c321ba5a01d7a 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_form/rule_form.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_form/rule_form.tsx @@ -839,6 +839,9 @@ export const RuleForm = ({ : { ...actionGroup, defaultActionMessage: ruleTypeModel?.defaultActionMessage } )} recoveryActionGroup={recoveryActionGroup} + setActionUseAlertDataForTemplate={(enabled: boolean, index: number) => { + setActionProperty('useAlertDataForTemplate', enabled, index); + }} setActionIdByIndex={(id: string, index: number) => setActionProperty('id', id, index)} setActionGroupIdByIndex={(group: string, index: number) => setActionProperty('group', group, index) diff --git a/x-pack/plugins/triggers_actions_ui/public/types.ts b/x-pack/plugins/triggers_actions_ui/public/types.ts index fbcfbc0d38297..bc0ce10d461e6 100644 --- a/x-pack/plugins/triggers_actions_ui/public/types.ts +++ b/x-pack/plugins/triggers_actions_ui/public/types.ts @@ -217,6 +217,7 @@ export interface ActionParamsProps { index: number; editAction: (key: string, value: RuleActionParam, index: number) => void; errors: IErrorObject; + ruleTypeId?: string; messageVariables?: ActionVariable[]; defaultMessage?: string; useDefaultMessage?: boolean; diff --git a/x-pack/plugins/triggers_actions_ui/server/index.ts b/x-pack/plugins/triggers_actions_ui/server/index.ts index 2fb306e19402b..4dfe9a569a4bd 100644 --- a/x-pack/plugins/triggers_actions_ui/server/index.ts +++ b/x-pack/plugins/triggers_actions_ui/server/index.ts @@ -6,7 +6,6 @@ */ import { PluginConfigDescriptor, PluginInitializerContext } from '@kbn/core/server'; import { configSchema, ConfigSchema } from './config'; -import { TriggersActionsPlugin } from './plugin'; export type { PluginStartContract } from './plugin'; export type { TimeSeriesQuery, CoreQueryParams } from './data'; @@ -29,4 +28,7 @@ export const config: PluginConfigDescriptor = { schema: configSchema, }; -export const plugin = (ctx: PluginInitializerContext) => new TriggersActionsPlugin(ctx); +export const plugin = async (ctx: PluginInitializerContext) => { + const { TriggersActionsPlugin } = await import('./plugin'); + return new TriggersActionsPlugin(ctx); +}; diff --git a/x-pack/plugins/triggers_actions_ui/tsconfig.json b/x-pack/plugins/triggers_actions_ui/tsconfig.json index d2d91cca3486b..600c5b6cdc7d5 100644 --- a/x-pack/plugins/triggers_actions_ui/tsconfig.json +++ b/x-pack/plugins/triggers_actions_ui/tsconfig.json @@ -55,7 +55,8 @@ "@kbn/dashboard-plugin", "@kbn/licensing-plugin", "@kbn/expressions-plugin", - "@kbn/serverless", + "@kbn/core-saved-objects-api-server", + "@kbn/serverless" ], "exclude": ["target/**/*"] } diff --git a/x-pack/plugins/upgrade_assistant/server/index.ts b/x-pack/plugins/upgrade_assistant/server/index.ts index 976e7f58bffc7..589e2ced114ce 100644 --- a/x-pack/plugins/upgrade_assistant/server/index.ts +++ b/x-pack/plugins/upgrade_assistant/server/index.ts @@ -6,10 +6,10 @@ */ import { PluginInitializerContext } from '@kbn/core/server'; -import { UpgradeAssistantServerPlugin } from './plugin'; export { config } from './config'; -export const plugin = (ctx: PluginInitializerContext) => { +export const plugin = async (ctx: PluginInitializerContext) => { + const { UpgradeAssistantServerPlugin } = await import('./plugin'); return new UpgradeAssistantServerPlugin(ctx); }; diff --git a/x-pack/plugins/uptime/server/index.ts b/x-pack/plugins/uptime/server/index.ts index 3ed326d1fc143..f1434bbd822dc 100644 --- a/x-pack/plugins/uptime/server/index.ts +++ b/x-pack/plugins/uptime/server/index.ts @@ -6,9 +6,10 @@ */ import { PluginInitializerContext } from '@kbn/core/server'; -import { Plugin } from './plugin'; -export const plugin = (initializerContext: PluginInitializerContext) => - new Plugin(initializerContext); +export const plugin = async (initializerContext: PluginInitializerContext) => { + const { Plugin } = await import('./plugin'); + return new Plugin(initializerContext); +}; export { config } from '../common/config'; diff --git a/x-pack/plugins/ux/server/index.ts b/x-pack/plugins/ux/server/index.ts index e1027a9235eb3..911d24e465ed6 100644 --- a/x-pack/plugins/ux/server/index.ts +++ b/x-pack/plugins/ux/server/index.ts @@ -6,9 +6,10 @@ */ import { PluginInitializerContext } from '@kbn/core/server'; -import { Plugin } from './plugin'; -export const plugin = (initializerContext: PluginInitializerContext) => - new Plugin(); +export const plugin = async (initializerContext: PluginInitializerContext) => { + const { Plugin } = await import('./plugin'); + return new Plugin(); +}; export { config } from '../common/config'; diff --git a/x-pack/plugins/watcher/server/index.ts b/x-pack/plugins/watcher/server/index.ts index 42a76820f0c20..383316ce9a2ec 100644 --- a/x-pack/plugins/watcher/server/index.ts +++ b/x-pack/plugins/watcher/server/index.ts @@ -8,9 +8,10 @@ import { PluginInitializerContext } from '@kbn/core/server'; import { offeringBasedSchema, schema } from '@kbn/config-schema'; -import { WatcherServerPlugin } from './plugin'; - -export const plugin = (ctx: PluginInitializerContext) => new WatcherServerPlugin(ctx); +export const plugin = async (ctx: PluginInitializerContext) => { + const { WatcherServerPlugin } = await import('./plugin'); + return new WatcherServerPlugin(ctx); +}; export const config = { schema: schema.object({ diff --git a/x-pack/test/alerting_api_integration/common/plugins/aad/server/index.ts b/x-pack/test/alerting_api_integration/common/plugins/aad/server/index.ts index 700aee6bfd49d..ed9e6682e0098 100644 --- a/x-pack/test/alerting_api_integration/common/plugins/aad/server/index.ts +++ b/x-pack/test/alerting_api_integration/common/plugins/aad/server/index.ts @@ -7,4 +7,4 @@ import { FixturePlugin } from './plugin'; -export const plugin = () => new FixturePlugin(); +export const plugin = async () => new FixturePlugin(); diff --git a/x-pack/test/alerting_api_integration/common/plugins/actions_simulators/server/bedrock_simulation.ts b/x-pack/test/alerting_api_integration/common/plugins/actions_simulators/server/bedrock_simulation.ts index bfa8c5cb0736f..29e77feb5edaf 100644 --- a/x-pack/test/alerting_api_integration/common/plugins/actions_simulators/server/bedrock_simulation.ts +++ b/x-pack/test/alerting_api_integration/common/plugins/actions_simulators/server/bedrock_simulation.ts @@ -7,6 +7,8 @@ import http from 'http'; +import { EventStreamCodec } from '@smithy/eventstream-codec'; +import { fromUtf8, toUtf8 } from '@smithy/util-utf8'; import { ProxyArgs, Simulator } from './simulator'; export class BedrockSimulator extends Simulator { @@ -27,6 +29,10 @@ export class BedrockSimulator extends Simulator { return BedrockSimulator.sendErrorResponse(response); } + if (request.url === '/model/anthropic.claude-v2/invoke-with-response-stream') { + return BedrockSimulator.sendStreamResponse(response); + } + return BedrockSimulator.sendResponse(response); } @@ -36,6 +42,14 @@ export class BedrockSimulator extends Simulator { response.end(JSON.stringify(bedrockSuccessResponse, null, 4)); } + private static sendStreamResponse(response: http.ServerResponse) { + response.statusCode = 200; + response.setHeader('Content-Type', 'application/octet-stream'); + response.setHeader('Transfer-Encoding', 'chunked'); + response.write(encodeBedrockResponse('Hello world, what a unique string!')); + response.end(); + } + private static sendErrorResponse(response: http.ServerResponse) { response.statusCode = 422; response.setHeader('Content-Type', 'application/json;charset=UTF-8'); @@ -52,3 +66,20 @@ export const bedrockFailedResponse = { message: 'Malformed input request: extraneous key [ooooo] is not permitted, please reformat your input and try again.', }; + +function encodeBedrockResponse(completion: string) { + return new EventStreamCodec(toUtf8, fromUtf8).encode({ + headers: { + ':event-type': { type: 'string', value: 'chunk' }, + ':content-type': { type: 'string', value: 'application/json' }, + ':message-type': { type: 'string', value: 'event' }, + }, + body: Uint8Array.from( + Buffer.from( + JSON.stringify({ + bytes: Buffer.from(JSON.stringify({ completion })).toString('base64'), + }) + ) + ), + }); +} diff --git a/x-pack/test/alerting_api_integration/common/plugins/actions_simulators/server/index.ts b/x-pack/test/alerting_api_integration/common/plugins/actions_simulators/server/index.ts index 700aee6bfd49d..ed9e6682e0098 100644 --- a/x-pack/test/alerting_api_integration/common/plugins/actions_simulators/server/index.ts +++ b/x-pack/test/alerting_api_integration/common/plugins/actions_simulators/server/index.ts @@ -7,4 +7,4 @@ import { FixturePlugin } from './plugin'; -export const plugin = () => new FixturePlugin(); +export const plugin = async () => new FixturePlugin(); diff --git a/x-pack/test/alerting_api_integration/common/plugins/alerts/server/index.ts b/x-pack/test/alerting_api_integration/common/plugins/alerts/server/index.ts index 5a260b165f792..ed2682aacbf14 100644 --- a/x-pack/test/alerting_api_integration/common/plugins/alerts/server/index.ts +++ b/x-pack/test/alerting_api_integration/common/plugins/alerts/server/index.ts @@ -8,4 +8,5 @@ import { PluginInitializerContext } from '@kbn/core/server'; import { FixturePlugin } from './plugin'; -export const plugin = (initContext: PluginInitializerContext) => new FixturePlugin(initContext); +export const plugin = async (initContext: PluginInitializerContext) => + new FixturePlugin(initContext); diff --git a/x-pack/test/alerting_api_integration/common/plugins/alerts_restricted/server/index.ts b/x-pack/test/alerting_api_integration/common/plugins/alerts_restricted/server/index.ts index 700aee6bfd49d..ed9e6682e0098 100644 --- a/x-pack/test/alerting_api_integration/common/plugins/alerts_restricted/server/index.ts +++ b/x-pack/test/alerting_api_integration/common/plugins/alerts_restricted/server/index.ts @@ -7,4 +7,4 @@ import { FixturePlugin } from './plugin'; -export const plugin = () => new FixturePlugin(); +export const plugin = async () => new FixturePlugin(); diff --git a/x-pack/test/alerting_api_integration/common/plugins/task_manager_fixture/server/index.ts b/x-pack/test/alerting_api_integration/common/plugins/task_manager_fixture/server/index.ts index bed262d69ea18..9ef27eac56335 100644 --- a/x-pack/test/alerting_api_integration/common/plugins/task_manager_fixture/server/index.ts +++ b/x-pack/test/alerting_api_integration/common/plugins/task_manager_fixture/server/index.ts @@ -7,4 +7,4 @@ import { SampleTaskManagerFixturePlugin } from './plugin'; -export const plugin = () => new SampleTaskManagerFixturePlugin(); +export const plugin = async () => new SampleTaskManagerFixturePlugin(); diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/create.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/create.ts index b7cf41d07e823..375eeaaffc44a 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/create.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/create.ts @@ -102,6 +102,7 @@ export default function createAlertTests({ getService }: FtrProviderContext) { group: 'default', params: {}, uuid: response.body.actions[0].uuid, + use_alert_data_for_template: false, }, ], enabled: true, diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/bedrock.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/bedrock.ts index 67053bef7801b..70cdc0f96dfdd 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/bedrock.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/bedrock.ts @@ -12,6 +12,7 @@ import { bedrockSuccessResponse, } from '@kbn/actions-simulators-plugin/server/bedrock_simulation'; import { DEFAULT_TOKEN_LIMIT } from '@kbn/stack-connectors-plugin/common/bedrock/constants'; +import { PassThrough } from 'stream'; import { FtrProviderContext } from '../../../../../common/ftr_provider_context'; import { getUrlPrefix, ObjectRemover } from '../../../../../common/lib'; @@ -407,6 +408,43 @@ export default function bedrockTest({ getService }: FtrProviderContext) { data: { message: bedrockSuccessResponse.completion }, }); }); + + it('should invoke stream with assistant AI body argument formatted to bedrock expectations', async () => { + await new Promise((resolve, reject) => { + let responseBody: string = ''; + + const passThrough = new PassThrough(); + + supertest + .post(`/internal/elastic_assistant/actions/connector/${bedrockActionId}/_execute`) + .set('kbn-xsrf', 'foo') + .on('error', reject) + .send({ + params: { + subAction: 'invokeStream', + subActionParams: { + messages: [ + { + role: 'user', + content: 'Hello world', + }, + ], + }, + }, + assistantLangChain: false, + }) + .pipe(passThrough); + + passThrough.on('data', (chunk) => { + responseBody += chunk.toString(); + }); + + passThrough.on('end', () => { + expect(responseBody).to.eql('Hello world, what a unique string!'); + resolve(); + }); + }); + }); }); }); diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/group3/tests/alerting/bulk_edit.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group3/tests/alerting/bulk_edit.ts index c948791e5ea49..ffd11e3fabd38 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/group3/tests/alerting/bulk_edit.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group3/tests/alerting/bulk_edit.ts @@ -116,6 +116,7 @@ export default function createUpdateTests({ getService }: FtrProviderContext) { params: {}, connector_type_id: 'test.noop', uuid: response.body.rules[0].actions[0].uuid, + use_alert_data_for_template: false, }, ]); expect(response.statusCode).to.eql(200); diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group1/create.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group1/create.ts index eb9f90cb41f2a..0577425103a8c 100644 --- a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group1/create.ts +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group1/create.ts @@ -78,6 +78,7 @@ export default function createAlertTests({ getService }: FtrProviderContext) { group: 'default', params: {}, uuid: response.body.actions[0].uuid, + use_alert_data_for_template: false, }, ], enabled: true, @@ -181,6 +182,7 @@ export default function createAlertTests({ getService }: FtrProviderContext) { group: 'default', params: {}, uuid: response.body.actions[0].uuid, + use_alert_data_for_template: false, }, { id: 'my-slack1', @@ -190,6 +192,7 @@ export default function createAlertTests({ getService }: FtrProviderContext) { message: 'something important happened!', }, uuid: response.body.actions[1].uuid, + use_alert_data_for_template: false, }, { id: 'system-connector-test.system-action', @@ -197,6 +200,7 @@ export default function createAlertTests({ getService }: FtrProviderContext) { connector_type_id: 'test.system-action', params: {}, uuid: response.body.actions[2].uuid, + use_alert_data_for_template: false, }, ], enabled: true, diff --git a/x-pack/test/api_integration/apis/transform/transforms_create.ts b/x-pack/test/api_integration/apis/transform/transforms_create.ts index e82f1d4fdfddc..84617f6990e3e 100644 --- a/x-pack/test/api_integration/apis/transform/transforms_create.ts +++ b/x-pack/test/api_integration/apis/transform/transforms_create.ts @@ -10,7 +10,7 @@ import { FtrProviderContext } from '../../ftr_provider_context'; import { getCommonRequestHeader } from '../../../functional/services/ml/common_api'; import { USER } from '../../../functional/services/transform/security_common'; -import { generateTransformConfig } from './common'; +import { generateTransformConfig, generateDestIndex } from './common'; export default ({ getService }: FtrProviderContext) => { const esArchiver = getService('esArchiver'); @@ -27,8 +27,102 @@ export default ({ getService }: FtrProviderContext) => { await transform.api.cleanTransformIndices(); }); + it('should create a transform', async () => { + const transformId = 'test_transform_id_create'; + + const { body, status } = await supertest + .put(`/internal/transform/transforms/${transformId}`) + .auth( + USER.TRANSFORM_POWERUSER, + transform.securityCommon.getPasswordForUser(USER.TRANSFORM_POWERUSER) + ) + .set(getCommonRequestHeader('1')) + .send({ + ...generateTransformConfig(transformId), + }); + + transform.api.assertResponseStatusCode(200, status, body); + + expect(body).to.eql({ + dataViewsCreated: [], + dataViewsErrors: [], + errors: [], + transformsCreated: [ + { + transform: transformId, + }, + ], + }); + }); + + it('should create a transform with data view', async () => { + const transformId = 'test_transform_id_create_with_data_view'; + const destinationIndex = generateDestIndex(transformId); + + const { body, status } = await supertest + .put(`/internal/transform/transforms/${transformId}?createDataView=true`) + .auth( + USER.TRANSFORM_POWERUSER, + transform.securityCommon.getPasswordForUser(USER.TRANSFORM_POWERUSER) + ) + .set(getCommonRequestHeader('1')) + .send({ + ...generateTransformConfig(transformId), + }); + + transform.api.assertResponseStatusCode(200, status, body); + + // The data view id will be returned as a non-deterministic uuid + // so we cannot assert the actual id returned. We'll just assert + // that a data view has been created a no errors were returned. + expect(body.dataViewsCreated.length).to.be(1); + expect(body.dataViewsErrors.length).to.be(0); + expect(body.errors.length).to.be(0); + expect(body.transformsCreated).to.eql([ + { + transform: transformId, + }, + ]); + + await transform.testResources.deleteIndexPatternByTitle(destinationIndex); + }); + + it('should create a transform with data view and time field', async () => { + const transformId = 'test_transform_id_create_with_data_view_and_time_field'; + const destinationIndex = generateDestIndex(transformId); + + const { body, status } = await supertest + .put( + `/internal/transform/transforms/${transformId}?createDataView=true&timeFieldName=@timestamp` + ) + .auth( + USER.TRANSFORM_POWERUSER, + transform.securityCommon.getPasswordForUser(USER.TRANSFORM_POWERUSER) + ) + .set(getCommonRequestHeader('1')) + .send({ + ...generateTransformConfig(transformId), + }); + + transform.api.assertResponseStatusCode(200, status, body); + + // The data view id will be returned as a non-deterministic uuid + // so we cannot assert the actual id returned. We'll just assert + // that a data view has been created a no errors were returned. + expect(body.dataViewsCreated.length).to.be(1); + expect(body.dataViewsErrors.length).to.be(0); + expect(body.errors.length).to.be(0); + expect(body.transformsCreated).to.eql([ + { + transform: transformId, + }, + ]); + + await transform.testResources.deleteIndexPatternByTitle(destinationIndex); + }); + it('should not allow pivot and latest configs in same transform', async () => { - const transformId = 'test_transform_id'; + const transformId = 'test_transform_id_fail'; const { body, status } = await supertest .put(`/internal/transform/transforms/${transformId}`) @@ -50,7 +144,7 @@ export default ({ getService }: FtrProviderContext) => { }); it('should ensure if pivot or latest is provided', async () => { - const transformId = 'test_transform_id'; + const transformId = 'test_transform_id_fail'; const { pivot, ...config } = generateTransformConfig(transformId); diff --git a/x-pack/test/api_integration/apis/transform/transforms_stats.ts b/x-pack/test/api_integration/apis/transform/transforms_stats.ts index aea5c049343e9..2eec1f4e17b9a 100644 --- a/x-pack/test/api_integration/apis/transform/transforms_stats.ts +++ b/x-pack/test/api_integration/apis/transform/transforms_stats.ts @@ -8,7 +8,7 @@ import expect from '@kbn/expect'; import type { GetTransformsStatsResponseSchema } from '@kbn/transform-plugin/common/api_schemas/transforms_stats'; -import { TRANSFORM_STATE } from '@kbn/transform-plugin/common/constants'; +import { TRANSFORM_STATE, type TransformState } from '@kbn/transform-plugin/common/constants'; import { getCommonRequestHeader } from '../../../functional/services/ml/common_api'; import { USER } from '../../../functional/services/transform/security_common'; @@ -17,45 +17,63 @@ import { FtrProviderContext } from '../../ftr_provider_context'; import { generateTransformConfig } from './common'; +interface ExpectedTransformsStats { + id: string; + state: TransformState; +} + export default ({ getService }: FtrProviderContext) => { const esArchiver = getService('esArchiver'); const supertest = getService('supertestWithoutAuth'); const transform = getService('transform'); - const expected = { - apiTransformTransforms: { - count: 2, - transform1: { id: 'transform-test-stats-1', state: TRANSFORM_STATE.STOPPED }, - transform2: { id: 'transform-test-stats-2', state: TRANSFORM_STATE.STOPPED }, - typeOfStats: 'object', - typeOfCheckpointing: 'object', - }, - }; + async function superTestRequest(endpoint: string, user: USER) { + return await supertest + .get(endpoint) + .auth(user, transform.securityCommon.getPasswordForUser(user)) + .set(getCommonRequestHeader('1')) + .send(); + } async function createTransform(transformId: string) { const config = generateTransformConfig(transformId); await transform.api.createTransform(transformId, config); } - function assertTransformsStatsResponseBody(body: GetTransformsStatsResponseSchema) { - expect(body.count).to.eql(expected.apiTransformTransforms.count); - expect(body.transforms).to.have.length(expected.apiTransformTransforms.count); + function assertTransformsStatsResponseBody( + body: GetTransformsStatsResponseSchema, + expectedTransformsStats: ExpectedTransformsStats[] + ) { + const expectedTransformsCount = expectedTransformsStats.length; - const transform1 = body.transforms[0]; - expect(transform1.id).to.eql(expected.apiTransformTransforms.transform1.id); - expect(transform1.state).to.eql(expected.apiTransformTransforms.transform1.state); - expect(typeof transform1.stats).to.eql(expected.apiTransformTransforms.typeOfStats); - expect(typeof transform1.checkpointing).to.eql( - expected.apiTransformTransforms.typeOfCheckpointing + expect(body.count).to.eql( + expectedTransformsCount, + `Expected response body count attribute to be ${expectedTransformsCount} (got ${body.count})` ); - - const transform2 = body.transforms[1]; - expect(transform2.id).to.eql(expected.apiTransformTransforms.transform2.id); - expect(transform2.state).to.eql(expected.apiTransformTransforms.transform2.state); - expect(typeof transform2.stats).to.eql(expected.apiTransformTransforms.typeOfStats); - expect(typeof transform2.checkpointing).to.eql( - expected.apiTransformTransforms.typeOfCheckpointing + expect(body.transforms).to.have.length( + expectedTransformsCount, + `Expected response body transforms count to be ${expectedTransformsCount} (got ${body.transforms.length})` ); + + expectedTransformsStats.forEach((expected, index) => { + const transformStats = body.transforms[index]; + expect(transformStats.id).to.eql( + expected.id, + `Expected transforms id to be ${expected.id} (got ${transformStats.id})` + ); + expect(transformStats.state).to.eql( + expected.state, + `Expected transforms state to be ${expected.state} (got ${transformStats.state})` + ); + expect(typeof transformStats.stats).to.eql( + 'object', + `Expected transforms stats type to be 'object' (got ${typeof transformStats.stats})` + ); + expect(typeof transformStats.checkpointing).to.eql( + 'object', + `Expected transforms checkpointing type to be 'object' (got ${typeof transformStats.checkpointing})` + ); + }); } describe('/internal/transform/transforms/_stats', function () { @@ -71,31 +89,57 @@ export default ({ getService }: FtrProviderContext) => { }); it('should return a list of transforms statistics for super-user', async () => { - const { body, status } = await supertest - .get('/internal/transform/transforms/_stats') - .auth( - USER.TRANSFORM_POWERUSER, - transform.securityCommon.getPasswordForUser(USER.TRANSFORM_POWERUSER) - ) - .set(getCommonRequestHeader('1')) - .send(); + const { body, status } = await superTestRequest( + '/internal/transform/transforms/_stats', + USER.TRANSFORM_POWERUSER + ); + transform.api.assertResponseStatusCode(200, status, body); - assertTransformsStatsResponseBody(body); + assertTransformsStatsResponseBody(body, [ + { id: 'transform-test-stats-1', state: TRANSFORM_STATE.STOPPED }, + { id: 'transform-test-stats-2', state: TRANSFORM_STATE.STOPPED }, + ]); + }); + + it('should return statistics for a single transform for super-user', async () => { + const { body, status } = await superTestRequest( + '/internal/transform/transforms/transform-test-stats-1/_stats', + USER.TRANSFORM_POWERUSER + ); + + transform.api.assertResponseStatusCode(200, status, body); + + assertTransformsStatsResponseBody(body, [ + { id: 'transform-test-stats-1', state: TRANSFORM_STATE.STOPPED }, + ]); }); it('should return a list of transforms statistics view-only user', async () => { - const { body, status } = await supertest - .get(`/internal/transform/transforms/_stats`) - .auth( - USER.TRANSFORM_VIEWER, - transform.securityCommon.getPasswordForUser(USER.TRANSFORM_VIEWER) - ) - .set(getCommonRequestHeader('1')) - .send(); + const { body, status } = await superTestRequest( + '/internal/transform/transforms/_stats', + USER.TRANSFORM_VIEWER + ); + + transform.api.assertResponseStatusCode(200, status, body); + + assertTransformsStatsResponseBody(body, [ + { id: 'transform-test-stats-1', state: TRANSFORM_STATE.STOPPED }, + { id: 'transform-test-stats-2', state: TRANSFORM_STATE.STOPPED }, + ]); + }); + + it('should return statistics for a single transform for view-only user', async () => { + const { body, status } = await superTestRequest( + '/internal/transform/transforms/transform-test-stats-2/_stats', + USER.TRANSFORM_VIEWER + ); + transform.api.assertResponseStatusCode(200, status, body); - assertTransformsStatsResponseBody(body); + assertTransformsStatsResponseBody(body, [ + { id: 'transform-test-stats-2', state: TRANSFORM_STATE.STOPPED }, + ]); }); }); }; diff --git a/x-pack/test/cases_api_integration/common/lib/api/index.ts b/x-pack/test/cases_api_integration/common/lib/api/index.ts index 361a00eadb518..4d7d64bbc4487 100644 --- a/x-pack/test/cases_api_integration/common/lib/api/index.ts +++ b/x-pack/test/cases_api_integration/common/lib/api/index.ts @@ -787,3 +787,24 @@ export const bulkGetCases = async ({ return res; }; + +export const searchCases = async ({ + supertest, + body = {}, + expectedHttpCode = 200, + auth = { user: superUser, space: null }, +}: { + supertest: SuperTest.SuperTest; + body?: Record; + expectedHttpCode?: number; + auth?: { user: User; space: string | null }; +}): Promise => { + const { body: res } = await supertest + .post(`${getSpaceUrlPrefix(auth.space)}${CASES_INTERNAL_URL}/_search`) + .auth(auth.user.username, auth.user.password) + .set('kbn-xsrf', 'true') + .send({ ...body }) + .expect(expectedHttpCode); + + return res; +}; diff --git a/x-pack/test/cases_api_integration/common/plugins/cases/server/index.ts b/x-pack/test/cases_api_integration/common/plugins/cases/server/index.ts index 50d0aa6df9b82..b84439c6851b0 100644 --- a/x-pack/test/cases_api_integration/common/plugins/cases/server/index.ts +++ b/x-pack/test/cases_api_integration/common/plugins/cases/server/index.ts @@ -8,5 +8,5 @@ import { PluginInitializerContext } from '@kbn/core/server'; import { FixturePlugin } from './plugin'; -export const plugin = (initializerContext: PluginInitializerContext) => +export const plugin = async (initializerContext: PluginInitializerContext) => new FixturePlugin(initializerContext); diff --git a/x-pack/test/cases_api_integration/common/plugins/observability/server/index.ts b/x-pack/test/cases_api_integration/common/plugins/observability/server/index.ts index 700aee6bfd49d..ed9e6682e0098 100644 --- a/x-pack/test/cases_api_integration/common/plugins/observability/server/index.ts +++ b/x-pack/test/cases_api_integration/common/plugins/observability/server/index.ts @@ -7,4 +7,4 @@ import { FixturePlugin } from './plugin'; -export const plugin = () => new FixturePlugin(); +export const plugin = async () => new FixturePlugin(); diff --git a/x-pack/test/cases_api_integration/common/plugins/security_solution/server/index.ts b/x-pack/test/cases_api_integration/common/plugins/security_solution/server/index.ts index 700aee6bfd49d..ed9e6682e0098 100644 --- a/x-pack/test/cases_api_integration/common/plugins/security_solution/server/index.ts +++ b/x-pack/test/cases_api_integration/common/plugins/security_solution/server/index.ts @@ -7,4 +7,4 @@ import { FixturePlugin } from './plugin'; -export const plugin = () => new FixturePlugin(); +export const plugin = async () => new FixturePlugin(); diff --git a/x-pack/test/cases_api_integration/security_and_spaces/tests/common/index.ts b/x-pack/test/cases_api_integration/security_and_spaces/tests/common/index.ts index a0aee09f47ed9..636c166169808 100644 --- a/x-pack/test/cases_api_integration/security_and_spaces/tests/common/index.ts +++ b/x-pack/test/cases_api_integration/security_and_spaces/tests/common/index.ts @@ -55,6 +55,7 @@ export default ({ loadTestFile }: FtrProviderContext): void => { loadTestFile(require.resolve('./internal/get_connectors')); loadTestFile(require.resolve('./internal/user_actions_get_users')); loadTestFile(require.resolve('./internal/bulk_delete_file_attachments')); + loadTestFile(require.resolve('./internal/search_cases')); /** * Attachments framework diff --git a/x-pack/test/cases_api_integration/security_and_spaces/tests/common/internal/search_cases.ts b/x-pack/test/cases_api_integration/security_and_spaces/tests/common/internal/search_cases.ts new file mode 100644 index 0000000000000..563a1d2ec83dc --- /dev/null +++ b/x-pack/test/cases_api_integration/security_and_spaces/tests/common/internal/search_cases.ts @@ -0,0 +1,940 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license 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 { CustomFieldTypes } from '@kbn/cases-plugin/common/types/domain'; +import { CASES_INTERNAL_URL } from '@kbn/cases-plugin/common/constants'; +import { CaseSeverity } from '@kbn/cases-plugin/common/types/domain'; + +import { FtrProviderContext } from '../../../../common/ftr_provider_context'; +import { postCaseReq, findCasesResp, getPostCaseRequest } from '../../../../common/lib/mock'; +import { + ensureSavedObjectIsAuthorized, + deleteAllCaseItems, + searchCases, + createCase, + createConfiguration, + getConfigurationRequest, +} from '../../../../common/lib/api'; +import { + obsOnly, + secOnly, + obsOnlyRead, + secOnlyRead, + noKibanaPrivileges, + superUser, + globalRead, + obsSecRead, + obsSec, +} from '../../../../common/lib/authentication/users'; + +// eslint-disable-next-line import/no-default-export +export default ({ getService }: FtrProviderContext): void => { + const supertest = getService('supertest'); + const supertestWithoutAuth = getService('supertestWithoutAuth'); + const es = getService('es'); + const kibanaServer = getService('kibanaServer'); + + describe('search_cases', () => { + afterEach(async () => { + await deleteAllCaseItems(es); + }); + + describe('basic tests', () => { + it('filters by single customField', async () => { + await createConfiguration( + supertest, + getConfigurationRequest({ + overrides: { + customFields: [ + { + key: 'valid_key_1', + label: 'text', + type: CustomFieldTypes.TEXT, + required: false, + }, + { + key: 'valid_key_2', + label: 'toggle', + type: CustomFieldTypes.TOGGLE, + required: true, + }, + ], + }, + }) + ); + + await createCase(supertest, { + ...postCaseReq, + customFields: [ + { + key: 'valid_key_1', + type: CustomFieldTypes.TEXT, + value: null, + }, + { + key: 'valid_key_2', + type: CustomFieldTypes.TOGGLE, + value: false, + }, + ], + }); + + const postedCase = await createCase(supertest, { + ...postCaseReq, + customFields: [ + { + key: 'valid_key_1', + type: CustomFieldTypes.TEXT, + value: 'this is a text field value', + }, + { + key: 'valid_key_2', + type: CustomFieldTypes.TOGGLE, + value: true, + }, + ], + }); + + const cases = await searchCases({ + supertest, + body: { customFields: { valid_key_2: [true] }, owner: 'securitySolutionFixture' }, + }); + + expect(cases).to.eql({ + ...findCasesResp, + total: 1, + cases: [postedCase], + count_open_cases: 1, + }); + }); + + it('filters by multiple customField', async () => { + await createConfiguration( + supertest, + getConfigurationRequest({ + overrides: { + customFields: [ + { + key: 'valid_key_1', + label: 'text', + type: CustomFieldTypes.TEXT, + required: false, + }, + { + key: 'valid_key_2', + label: 'toggle', + type: CustomFieldTypes.TOGGLE, + required: true, + }, + { + key: 'valid_key_3', + label: 'another_toggle', + type: CustomFieldTypes.TOGGLE, + required: false, + }, + ], + }, + }) + ); + + await createCase(supertest, { + ...postCaseReq, + customFields: [ + { + key: 'valid_key_1', + type: CustomFieldTypes.TEXT, + value: null, + }, + { + key: 'valid_key_2', + type: CustomFieldTypes.TOGGLE, + value: false, + }, + { + key: 'valid_key_3', + type: CustomFieldTypes.TOGGLE, + value: true, + }, + ], + }); + + const postedCase2 = await createCase(supertest, { + ...postCaseReq, + customFields: [ + { + key: 'valid_key_1', + type: CustomFieldTypes.TEXT, + value: 'this is a text field value', + }, + { + key: 'valid_key_2', + type: CustomFieldTypes.TOGGLE, + value: true, + }, + { + key: 'valid_key_3', + type: CustomFieldTypes.TOGGLE, + value: false, + }, + ], + }); + + const cases = await searchCases({ + supertest, + body: { + customFields: { valid_key_2: [true], valid_key_3: [false] }, + owner: 'securitySolutionFixture', + }, + }); + + expect(cases).to.eql({ + ...findCasesResp, + total: 1, + cases: [postedCase2], + count_open_cases: 1, + }); + }); + + it('filters by customField with correct owner', async () => { + await createConfiguration( + supertest, + getConfigurationRequest({ + overrides: { + customFields: [ + { + key: 'valid_key_1', + label: 'text', + type: CustomFieldTypes.TEXT, + required: false, + }, + { + key: 'valid_key_2', + label: 'toggle', + type: CustomFieldTypes.TOGGLE, + required: true, + }, + { + key: 'valid_key_3', + label: 'another_toggle', + type: CustomFieldTypes.TOGGLE, + required: false, + }, + ], + }, + }) + ); + + await createConfiguration( + supertest, + getConfigurationRequest({ + overrides: { + customFields: [ + { + key: 'valid_obs_key_1', + label: 'text', + type: CustomFieldTypes.TEXT, + required: false, + }, + { + key: 'valid_obs_key_2', + label: 'toggle', + type: CustomFieldTypes.TOGGLE, + required: true, + }, + { + key: 'valid_obs_key_3', + label: 'another_toggle', + type: CustomFieldTypes.TOGGLE, + required: false, + }, + ], + owner: 'observabilityFixture', + }, + }) + ); + + const secCase = await createCase(supertest, { + ...postCaseReq, + owner: 'securitySolutionFixture', + customFields: [ + { + key: 'valid_key_1', + type: CustomFieldTypes.TEXT, + value: null, + }, + { + key: 'valid_key_2', + type: CustomFieldTypes.TOGGLE, + value: false, + }, + { + key: 'valid_key_3', + type: CustomFieldTypes.TOGGLE, + value: true, + }, + ], + }); + + const obsCase = await createCase(supertest, { + ...postCaseReq, + owner: 'observabilityFixture', + customFields: [ + { + key: 'valid_obs_key_1', + type: CustomFieldTypes.TEXT, + value: null, + }, + { + key: 'valid_obs_key_2', + type: CustomFieldTypes.TOGGLE, + value: false, + }, + { + key: 'valid_obs_key_3', + type: CustomFieldTypes.TOGGLE, + value: true, + }, + ], + }); + + expect( + await searchCases({ + supertest, + body: { customFields: { valid_key_2: [false] }, owner: 'securitySolutionFixture' }, + }) + ).to.eql({ + ...findCasesResp, + total: 1, + cases: [secCase], + count_open_cases: 1, + }); + + expect( + await searchCases({ + supertest, + body: { customFields: { valid_obs_key_2: [false] }, owner: 'observabilityFixture' }, + }) + ).to.eql({ + ...findCasesResp, + total: 1, + cases: [obsCase], + count_open_cases: 1, + }); + }); + + it('filters by customField and tags', async () => { + await createConfiguration( + supertest, + getConfigurationRequest({ + overrides: { + customFields: [ + { + key: 'valid_key_1', + label: 'text', + type: CustomFieldTypes.TEXT, + required: false, + }, + { + key: 'valid_key_2', + label: 'toggle', + type: CustomFieldTypes.TOGGLE, + required: true, + }, + ], + }, + }) + ); + + await createCase(supertest, { + ...postCaseReq, + customFields: [ + { + key: 'valid_key_1', + type: CustomFieldTypes.TEXT, + value: null, + }, + { + key: 'valid_key_2', + type: CustomFieldTypes.TOGGLE, + value: false, + }, + ], + }); + + const postedCase = await createCase(supertest, { + ...postCaseReq, + customFields: [ + { + key: 'valid_key_1', + type: CustomFieldTypes.TEXT, + value: 'this is a text field value', + }, + { + key: 'valid_key_2', + type: CustomFieldTypes.TOGGLE, + value: true, + }, + ], + tags: ['unique'], + }); + + const cases = await searchCases({ + supertest, + body: { + customFields: { valid_key_2: [true] }, + tags: ['unique'], + owner: 'securitySolutionFixture', + }, + }); + + expect(cases).to.eql({ + ...findCasesResp, + total: 1, + cases: [postedCase], + count_open_cases: 1, + }); + }); + }); + + describe('errors', () => { + it('unhappy path - 400s when no owner', async () => { + await createConfiguration( + supertest, + getConfigurationRequest({ + overrides: { + customFields: [ + { + key: 'valid_key_1', + label: 'text', + type: CustomFieldTypes.TEXT, + required: false, + }, + { + key: 'valid_key_2', + label: 'toggle', + type: CustomFieldTypes.TOGGLE, + required: true, + }, + ], + owner: 'securitySolutionFixture', + }, + }) + ); + + await searchCases({ + supertest, + body: { customFields: { valid_key_2: [false] } }, + expectedHttpCode: 400, + }); + }); + + it('unhappy path - 400s when multiple owners', async () => { + await createConfiguration( + supertest, + getConfigurationRequest({ + overrides: { + customFields: [ + { + key: 'valid_key_1', + label: 'text', + type: CustomFieldTypes.TEXT, + required: false, + }, + { + key: 'valid_key_2', + label: 'toggle', + type: CustomFieldTypes.TOGGLE, + required: true, + }, + ], + owner: 'securitySolutionFixture', + }, + }) + ); + + await createConfiguration( + supertest, + getConfigurationRequest({ + overrides: { + customFields: [ + { + key: 'valid_obs_key_1', + label: 'text', + type: CustomFieldTypes.TEXT, + required: false, + }, + { + key: 'valid_obs_key_2', + label: 'toggle', + type: CustomFieldTypes.TOGGLE, + required: true, + }, + { + key: 'valid_obs_key_3', + label: 'another_toggle', + type: CustomFieldTypes.TOGGLE, + required: false, + }, + ], + owner: 'observabilityFixture', + }, + }) + ); + + await searchCases({ + supertest, + body: { + customFields: { valid_key_2: [false], valid_obs_key_2: [false] }, + owner: ['observabilityFixture', 'securitySolutionFixture'], + }, + expectedHttpCode: 400, + }); + }); + + it('unhappy path - 400s when customFieldConfiguration owner and search customFields owner are different ', async () => { + await createConfiguration( + supertest, + getConfigurationRequest({ + overrides: { + customFields: [ + { + key: 'valid_key_1', + label: 'text', + type: CustomFieldTypes.TEXT, + required: false, + }, + { + key: 'valid_key_2', + label: 'toggle', + type: CustomFieldTypes.TOGGLE, + required: true, + }, + ], + owner: 'securitySolutionFixture', + }, + }) + ); + + await searchCases({ + supertest, + body: { customFields: { valid_key_2: [false] }, owner: 'observabilityFixture' }, + expectedHttpCode: 400, + }); + }); + + it('unhappy path - 400s when configuration is empty', async () => { + await createConfiguration(supertest, getConfigurationRequest({})); + await searchCases({ + supertest, + body: { customFields: { random_key: [false] }, owner: 'securitySolutionFixture' }, + expectedHttpCode: 400, + }); + }); + + it('unhappy path - 400s when invalid custom field key passed', async () => { + await createConfiguration( + supertest, + getConfigurationRequest({ + overrides: { + customFields: [ + { + key: 'valid_key_1', + label: 'text', + type: CustomFieldTypes.TEXT, + required: false, + }, + { + key: 'valid_key_2', + label: 'toggle', + type: CustomFieldTypes.TOGGLE, + required: true, + }, + ], + }, + }) + ); + + await searchCases({ + supertest, + body: { customFields: { random_key: [false] }, owner: 'securitySolutionFixture' }, + expectedHttpCode: 400, + }); + }); + + it('unhappy path - 400s when invalid value of custom field', async () => { + await createConfiguration( + supertest, + getConfigurationRequest({ + overrides: { + customFields: [ + { + key: 'valid_key_1', + label: 'text', + type: CustomFieldTypes.TEXT, + required: false, + }, + { + key: 'valid_key_2', + label: 'toggle', + type: CustomFieldTypes.TOGGLE, + required: true, + }, + ], + }, + }) + ); + + await searchCases({ + supertest, + body: { customFields: { valid_key_2: [1234] }, owner: 'securitySolutionFixture' }, + expectedHttpCode: 400, + }); + }); + + it('unhappy path - 400s when custom field type is non filterable', async () => { + await createConfiguration( + supertest, + getConfigurationRequest({ + overrides: { + customFields: [ + { + key: 'valid_key_1', + label: 'text', + type: CustomFieldTypes.TEXT, + required: false, + }, + { + key: 'valid_key_2', + label: 'toggle', + type: CustomFieldTypes.TOGGLE, + required: true, + }, + ], + }, + }) + ); + + await searchCases({ + supertest, + body: { customFields: { valid_key_1: ['hello!'] }, owner: 'securitySolutionFixture' }, + expectedHttpCode: 400, + }); + }); + }); + + describe('rbac', () => { + afterEach(async () => { + await deleteAllCaseItems(es); + }); + + it('should return the correct cases', async () => { + await Promise.all([ + // Create case owned by the security solution user + createCase( + supertestWithoutAuth, + getPostCaseRequest({ owner: 'securitySolutionFixture' }), + 200, + { + user: secOnly, + space: 'space1', + } + ), + // Create case owned by the observability user + createCase( + supertestWithoutAuth, + getPostCaseRequest({ owner: 'observabilityFixture' }), + 200, + { + user: obsOnly, + space: 'space1', + } + ), + ]); + + for (const scenario of [ + { + user: globalRead, + numberOfExpectedCases: 2, + owners: ['securitySolutionFixture', 'observabilityFixture'], + }, + { + user: superUser, + numberOfExpectedCases: 2, + owners: ['securitySolutionFixture', 'observabilityFixture'], + }, + { user: secOnlyRead, numberOfExpectedCases: 1, owners: ['securitySolutionFixture'] }, + { user: obsOnlyRead, numberOfExpectedCases: 1, owners: ['observabilityFixture'] }, + { + user: obsSecRead, + numberOfExpectedCases: 2, + owners: ['securitySolutionFixture', 'observabilityFixture'], + }, + ]) { + const res = await searchCases({ + supertest: supertestWithoutAuth, + auth: { + user: scenario.user, + space: 'space1', + }, + body: { owner: ['securitySolutionFixture', 'observabilityFixture'] }, + }); + + ensureSavedObjectIsAuthorized(res.cases, scenario.numberOfExpectedCases, scenario.owners); + } + }); + + for (const scenario of [ + { user: noKibanaPrivileges, space: 'space1' }, + { user: secOnly, space: 'space2' }, + ]) { + it(`User ${scenario.user.username} with role(s) ${scenario.user.roles.join()} and space ${ + scenario.space + } - should NOT read a case`, async () => { + // super user creates a case at the appropriate space + await createCase( + supertestWithoutAuth, + getPostCaseRequest({ owner: 'securitySolutionFixture' }), + 200, + { + user: superUser, + space: scenario.space, + } + ); + + // user should not be able to read cases at the appropriate space + await searchCases({ + supertest: supertestWithoutAuth, + auth: { + user: scenario.user, + space: scenario.space, + }, + body: { owner: 'securitySolutionFixture' }, + expectedHttpCode: 403, + }); + }); + } + + // This test is to prevent a future developer to add the filter attribute without taking into consideration + // the authorizationFilter produced by the cases authorization class + it('should NOT allow to pass a filter', async () => { + await supertest + .post(`${CASES_INTERNAL_URL}/_search`) + .set('kbn-xsrf', 'true') + .send({ + sortOrder: 'asc', + filter: `{cases.attributes.owner:"observabilityFixture"}`, + owner: 'observabilityFixture', + }) + .expect(400); + }); + + it('should NOT allow to pass non-valid fields', async () => { + await searchCases({ + supertest, + body: { + searchFields: ['foobar'], + search: 'some search string*', + owner: 'observabilityFixture', + }, + expectedHttpCode: 400, + }); + }); + + // This test ensures that the user is not allowed to define the namespaces query param + // so she cannot search across spaces + it('should NOT allow to pass a namespaces', async () => { + await supertest + .post(`${CASES_INTERNAL_URL}/_search`) + .set('kbn-xsrf', 'true') + .send({ + sortOrder: 'asc', + filter: `{namespaces[0]=*}`, + owner: 'observabilityFixture', + }) + .expect(400); + + await supertest + .post(`${CASES_INTERNAL_URL}/_search`) + .set('kbn-xsrf', 'true') + .send({ + sortOrder: 'asc', + namespaces: '*', + owner: 'observabilityFixture', + }) + .expect(400); + }); + + it('should NOT allow to pass a non supported query parameter', async () => { + await supertest + .post(`${CASES_INTERNAL_URL}/_search`) + .set('kbn-xsrf', 'true') + .send({ notExists: 'papa', owner: 'observabilityFixture' }) + .expect(400); + }); + + it('should respect the owner filter when having permissions', async () => { + await Promise.all([ + createCase( + supertestWithoutAuth, + getPostCaseRequest({ owner: 'securitySolutionFixture' }), + 200, + { + user: obsSec, + space: 'space1', + } + ), + createCase( + supertestWithoutAuth, + getPostCaseRequest({ owner: 'observabilityFixture' }), + 200, + { + user: obsSec, + space: 'space1', + } + ), + ]); + + const res = await searchCases({ + supertest: supertestWithoutAuth, + body: { + owner: 'securitySolutionFixture', + }, + auth: { + user: obsSec, + space: 'space1', + }, + }); + + ensureSavedObjectIsAuthorized(res.cases, 1, ['securitySolutionFixture']); + }); + + it('should return the correct cases when trying to exploit RBAC through the owner query parameter', async () => { + await Promise.all([ + createCase( + supertestWithoutAuth, + getPostCaseRequest({ owner: 'securitySolutionFixture' }), + 200, + { + user: obsSec, + space: 'space1', + } + ), + createCase( + supertestWithoutAuth, + getPostCaseRequest({ owner: 'observabilityFixture' }), + 200, + { + user: obsSec, + space: 'space1', + } + ), + ]); + + // User with permissions only to security solution request cases from observability + const res = await searchCases({ + supertest: supertestWithoutAuth, + body: { + owner: ['securitySolutionFixture', 'observabilityFixture'], + }, + auth: { + user: secOnly, + space: 'space1', + }, + }); + + // Only security solution cases are being returned + ensureSavedObjectIsAuthorized(res.cases, 1, ['securitySolutionFixture']); + }); + + describe('range queries', () => { + before(async () => { + await kibanaServer.importExport.load( + 'x-pack/test/functional/fixtures/kbn_archiver/cases/8.2.0/cases_various_dates.json', + { space: 'space1' } + ); + }); + + after(async () => { + await kibanaServer.importExport.unload( + 'x-pack/test/functional/fixtures/kbn_archiver/cases/8.2.0/cases_various_dates.json', + { space: 'space1' } + ); + await deleteAllCaseItems(es); + }); + + it('should respect the owner filter when using range queries', async () => { + const res = await searchCases({ + supertest: supertestWithoutAuth, + body: { + from: '2022-03-15', + to: '2022-03-21', + owner: 'securitySolutionFixture', + }, + auth: { + user: secOnly, + space: 'space1', + }, + }); + + // Only security solution cases are being returned + ensureSavedObjectIsAuthorized(res.cases, 1, ['securitySolutionFixture']); + }); + }); + + describe('RBAC query filter', () => { + it('should return the correct cases when trying to query filter by severity', async () => { + await Promise.all([ + createCase( + supertestWithoutAuth, + getPostCaseRequest({ owner: 'securitySolutionFixture', severity: CaseSeverity.HIGH }), + 200, + { + user: obsSec, + space: 'space1', + } + ), + createCase( + supertestWithoutAuth, + getPostCaseRequest({ owner: 'securitySolutionFixture', severity: CaseSeverity.HIGH }), + 200, + { + user: obsSec, + space: 'space1', + } + ), + createCase( + supertestWithoutAuth, + getPostCaseRequest({ owner: 'observabilityFixture', severity: CaseSeverity.HIGH }), + 200, + { + user: obsOnly, + space: 'space1', + } + ), + ]); + + // User with permissions only to security solution should get only the security solution cases + const res = await searchCases({ + supertest: supertestWithoutAuth, + body: { + severity: CaseSeverity.HIGH, + owner: 'securitySolutionFixture', + }, + auth: { + user: secOnly, + space: 'space1', + }, + }); + + // Only security solution cases are being returned + ensureSavedObjectIsAuthorized(res.cases, 2, ['securitySolutionFixture']); + }); + }); + }); + }); +}; diff --git a/x-pack/test/cloud_integration/plugins/saml_provider/server/index.ts b/x-pack/test/cloud_integration/plugins/saml_provider/server/index.ts index ff490693e86a2..c0c10de01fb49 100644 --- a/x-pack/test/cloud_integration/plugins/saml_provider/server/index.ts +++ b/x-pack/test/cloud_integration/plugins/saml_provider/server/index.ts @@ -8,7 +8,7 @@ import { PluginInitializer, Plugin } from '@kbn/core/server'; import { initRoutes } from './init_routes'; -export const plugin: PluginInitializer = (): Plugin => ({ +export const plugin: PluginInitializer = async (): Promise => ({ setup: (core) => initRoutes(core), start: () => {}, stop: () => {}, diff --git a/x-pack/plugins/reporting/server/export_types/csv_searchsource/types.ts b/x-pack/test/dataset_quality_api_integration/basic/config.ts similarity index 67% rename from x-pack/plugins/reporting/server/export_types/csv_searchsource/types.ts rename to x-pack/test/dataset_quality_api_integration/basic/config.ts index 1fef8eb47a8c9..614f052c9c774 100644 --- a/x-pack/plugins/reporting/server/export_types/csv_searchsource/types.ts +++ b/x-pack/test/dataset_quality_api_integration/basic/config.ts @@ -5,7 +5,7 @@ * 2.0. */ -export type { - JobParamsCSV, - TaskPayloadCSV, -} from '../../../common/types/export_types/csv_searchsource'; +import { configs } from '../configs'; + +// eslint-disable-next-line import/no-default-export +export default configs.basic; diff --git a/x-pack/test/dataset_quality_api_integration/common/config.ts b/x-pack/test/dataset_quality_api_integration/common/config.ts new file mode 100644 index 0000000000000..7a0c7c08fb2f0 --- /dev/null +++ b/x-pack/test/dataset_quality_api_integration/common/config.ts @@ -0,0 +1,154 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { + DatasetQualityUsername, + DATASET_QUALITY_TEST_PASSWORD, +} from '@kbn/dataset-quality-plugin/server/test_helpers/create_dataset_quality_users/authentication'; +import { createDatasetQualityUsers } from '@kbn/dataset-quality-plugin/server/test_helpers/create_dataset_quality_users'; +import { FtrConfigProviderContext } from '@kbn/test'; +import supertest from 'supertest'; +import { format, UrlObject } from 'url'; +import { + FtrProviderContext, + InheritedFtrProviderContext, + InheritedServices, +} from './ftr_provider_context'; +import { createDatasetQualityApiClient } from './dataset_quality_api_supertest'; +import { RegistryProvider } from './registry'; +import { DatasetQualityFtrConfigName } from '../configs'; + +export interface DatasetQualityFtrConfig { + name: DatasetQualityFtrConfigName; + license: 'basic'; + kibanaConfig?: Record; +} + +async function getDatasetQualityApiClient({ + kibanaServer, + username, +}: { + kibanaServer: UrlObject; + username: DatasetQualityUsername | 'elastic'; +}) { + const url = format({ + ...kibanaServer, + auth: `${username}:${DATASET_QUALITY_TEST_PASSWORD}`, + }); + + return createDatasetQualityApiClient(supertest(url)); +} + +export type CreateTestConfig = ReturnType; + +export type DatasetQualityApiClientKey = + | 'noAccessUser' + | 'readUser' + | 'adminUser' + | 'writeUser' + | 'datasetQualityLogsUser'; + +export type DatasetQualityApiClient = Record< + DatasetQualityApiClientKey, + Awaited> +>; + +export interface CreateTest { + testFiles: string[]; + servers: any; + servicesRequiredForTestAnalysis: string[]; + services: InheritedServices & { + datasetQualityFtrConfig: () => DatasetQualityFtrConfig; + registry: ({ getService }: FtrProviderContext) => ReturnType; + datasetQualityApiClient: (context: InheritedFtrProviderContext) => DatasetQualityApiClient; + }; + junit: { reportName: string }; + esTestCluster: any; + kbnTestServer: any; +} + +export function createTestConfig( + config: DatasetQualityFtrConfig +): ({ readConfigFile }: FtrConfigProviderContext) => Promise { + const { license, name, kibanaConfig } = config; + + return async ({ readConfigFile }: FtrConfigProviderContext) => { + const xPackAPITestsConfig = await readConfigFile( + require.resolve('../../api_integration/config.ts') + ); + + const services = xPackAPITestsConfig.get('services'); + const servers = xPackAPITestsConfig.get('servers'); + const kibanaServer = servers.kibana as UrlObject; + const kibanaServerUrl = format(kibanaServer); + const esServer = servers.elasticsearch as UrlObject; + + return { + testFiles: [require.resolve('../tests')], + servers, + servicesRequiredForTestAnalysis: ['datasetQualityFtrConfig', 'registry'], + services: { + ...services, + datasetQualityFtrConfig: () => config, + registry: RegistryProvider, + datasetQualityApiClient: async (_: InheritedFtrProviderContext) => { + const { username, password } = servers.kibana; + const esUrl = format(esServer); + + // Creates DatasetQuality users + await createDatasetQualityUsers({ + elasticsearch: { node: esUrl, username, password }, + kibana: { hostname: kibanaServerUrl }, + }); + + return { + noAccessUser: await getDatasetQualityApiClient({ + kibanaServer, + username: DatasetQualityUsername.noAccessUser, + }), + readUser: await getDatasetQualityApiClient({ + kibanaServer, + username: DatasetQualityUsername.viewerUser, + }), + adminUser: await getDatasetQualityApiClient({ + kibanaServer, + username: 'elastic', + }), + writeUser: await getDatasetQualityApiClient({ + kibanaServer, + username: DatasetQualityUsername.editorUser, + }), + datasetQualityLogsUser: await getDatasetQualityApiClient({ + kibanaServer, + username: DatasetQualityUsername.datasetQualityLogsUser, + }), + }; + }, + }, + junit: { + reportName: `Dataset quality API Integration tests (${name})`, + }, + esTestCluster: { + ...xPackAPITestsConfig.get('esTestCluster'), + license, + }, + kbnTestServer: { + ...xPackAPITestsConfig.get('kbnTestServer'), + serverArgs: [ + ...xPackAPITestsConfig.get('kbnTestServer.serverArgs'), + ...(kibanaConfig + ? Object.entries(kibanaConfig).map(([key, value]) => + Array.isArray(value) ? `--${key}=${JSON.stringify(value)}` : `--${key}=${value}` + ) + : []), + ], + }, + }; + }; +} + +export type DatasetQualityServices = Awaited>['services']; diff --git a/x-pack/test/dataset_quality_api_integration/common/dataset_quality_api_supertest.ts b/x-pack/test/dataset_quality_api_integration/common/dataset_quality_api_supertest.ts new file mode 100644 index 0000000000000..d28ddb5f04962 --- /dev/null +++ b/x-pack/test/dataset_quality_api_integration/common/dataset_quality_api_supertest.ts @@ -0,0 +1,95 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { format } from 'url'; +import supertest from 'supertest'; +import request from 'superagent'; +import type { APIEndpoint } from '@kbn/dataset-quality-plugin/server/routes'; +import { formatRequest } from '@kbn/server-route-repository'; +import { + APIClientRequestParamsOf, + APIReturnType, +} from '@kbn/dataset-quality-plugin/public/services/rest/create_call_dataset_quality_api'; + +export function createDatasetQualityApiClient(st: supertest.SuperTest) { + return async ( + options: { + type?: 'form-data'; + endpoint: TEndpoint; + } & APIClientRequestParamsOf & { params?: { query?: { _inspect?: boolean } } } + ): Promise> => { + const { endpoint, type } = options; + + const params = 'params' in options ? (options.params as Record) : {}; + + const { method, pathname, version } = formatRequest(endpoint, params.path); + const url = format({ pathname, query: params?.query }); + + const headers: Record = { 'kbn-xsrf': 'foo' }; + + if (version) { + headers['Elastic-Api-Version'] = version; + } + + let res: request.Response; + if (type === 'form-data') { + const fields: Array<[string, any]> = Object.entries(params.body); + const formDataRequest = st[method](url) + .set(headers) + .set('Content-type', 'multipart/form-data'); + + for (const field of fields) { + formDataRequest.field(field[0], field[1]); + } + + res = await formDataRequest; + } else if (params.body) { + res = await st[method](url).send(params.body).set(headers); + } else { + res = await st[method](url).set(headers); + } + + // supertest doesn't throw on http errors + if (res?.status !== 200) { + throw new DatasetQualityApiError(res, endpoint); + } + + return res; + }; +} + +type ApiErrorResponse = Omit & { + body: { + statusCode: number; + error: string; + message: string; + attributes: object; + }; +}; + +export type DatasetQualityApiSupertest = ReturnType; + +export class DatasetQualityApiError extends Error { + res: ApiErrorResponse; + + constructor(res: request.Response, endpoint: string) { + super( + `Unhandled DatasetQualityApiError. + Status: "${res.status}" + Endpoint: "${endpoint}" + Body: ${JSON.stringify(res.body)} + ` + ); + + this.res = res; + } +} + +export interface SupertestReturnType { + status: number; + body: APIReturnType; +} diff --git a/x-pack/test/dataset_quality_api_integration/common/ftr_provider_context.ts b/x-pack/test/dataset_quality_api_integration/common/ftr_provider_context.ts new file mode 100644 index 0000000000000..69de63c48402c --- /dev/null +++ b/x-pack/test/dataset_quality_api_integration/common/ftr_provider_context.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 { GenericFtrProviderContext } from '@kbn/test'; +import { FtrProviderContext as InheritedFtrProviderContext } from '../../api_integration/ftr_provider_context'; +import { DatasetQualityServices } from './config'; + +export type InheritedServices = InheritedFtrProviderContext extends GenericFtrProviderContext< + infer TServices, + {} +> + ? TServices + : {}; + +export type { InheritedFtrProviderContext }; +export type FtrProviderContext = GenericFtrProviderContext; diff --git a/x-pack/test/dataset_quality_api_integration/common/registry.ts b/x-pack/test/dataset_quality_api_integration/common/registry.ts new file mode 100644 index 0000000000000..355824916f873 --- /dev/null +++ b/x-pack/test/dataset_quality_api_integration/common/registry.ts @@ -0,0 +1,123 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { castArray, groupBy } from 'lodash'; +import callsites from 'callsites'; +import { FtrProviderContext } from './ftr_provider_context'; +import { DatasetQualityFtrConfigName } from '../configs'; +import { joinByKey, maybe } from '../utils'; + +interface RunCondition { + config: DatasetQualityFtrConfigName; +} + +export function RegistryProvider({ getService }: FtrProviderContext) { + const datasetQualityFtrConfig = getService('datasetQualityFtrConfig'); + + const callbacks: Array< + RunCondition & { + runs: Array<{ + cb: () => void; + }>; + } + > = []; + + let running: boolean = false; + + function when( + title: string, + conditions: RunCondition | RunCondition[], + callback: (condition: RunCondition) => void, + skip?: boolean + ) { + const allConditions = castArray(conditions); + + if (!allConditions.length) { + throw new Error('At least one condition should be defined'); + } + + if (running) { + throw new Error("Can't add tests when running"); + } + + const frame = maybe(callsites()[1]); + + const file = frame?.getFileName(); + + if (!file) { + throw new Error('Could not infer file for suite'); + } + + allConditions.forEach((matchedCondition) => { + callbacks.push({ + ...matchedCondition, + runs: [ + { + cb: () => { + const suite: ReturnType = (skip ? describe.skip : describe)( + title, + () => { + callback(matchedCondition); + } + ) as any; + + suite.file = file; + suite.eachTest((test) => { + test.file = file; + }); + }, + }, + ], + }); + }); + } + + when.skip = ( + title: string, + conditions: RunCondition | RunCondition[], + callback: (condition: RunCondition) => void + ) => { + when(title, conditions, callback, true); + }; + + const registry = { + when, + run: () => { + running = true; + + const groups = joinByKey(callbacks, ['config'], (a, b) => ({ + ...a, + ...b, + runs: a.runs.concat(b.runs), + })); + + callbacks.length = 0; + + const byConfig = groupBy(groups, 'config'); + + Object.keys(byConfig).forEach((config) => { + const groupsForConfig = byConfig[config]; + + // register suites for other configs, but skip them so tests are marked as such + // and their snapshots are not marked as obsolete + (config === datasetQualityFtrConfig.name ? describe : describe.skip)(config, () => { + groupsForConfig.forEach((group) => { + const { runs } = group; + + runs.forEach((run) => { + run.cb(); + }); + }); + }); + }); + + running = false; + }, + }; + + return registry; +} diff --git a/x-pack/test/dataset_quality_api_integration/configs/index.ts b/x-pack/test/dataset_quality_api_integration/configs/index.ts new file mode 100644 index 0000000000000..db4447b0bcfea --- /dev/null +++ b/x-pack/test/dataset_quality_api_integration/configs/index.ts @@ -0,0 +1,36 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { mapValues } from 'lodash'; +import { createTestConfig, CreateTestConfig } from '../common/config'; + +export const datasetQualityDebugLogger = { + name: 'plugins.datasetQuality', + level: 'debug', + appenders: ['console'], +}; + +const datasetQualityFtrConfigs = { + basic: { + license: 'basic' as const, + kibanaConfig: { + 'logging.loggers': [datasetQualityDebugLogger], + }, + }, +}; + +export type DatasetQualityFtrConfigName = keyof typeof datasetQualityFtrConfigs; + +export const configs: Record = mapValues( + datasetQualityFtrConfigs, + (value, key) => { + return createTestConfig({ + name: key as DatasetQualityFtrConfigName, + ...value, + }); + } +); diff --git a/x-pack/test/dataset_quality_api_integration/tests/data_streams.spec.ts b/x-pack/test/dataset_quality_api_integration/tests/data_streams.spec.ts new file mode 100644 index 0000000000000..cd236c109c667 --- /dev/null +++ b/x-pack/test/dataset_quality_api_integration/tests/data_streams.spec.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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import expect from '@kbn/expect'; +import { DatasetQualityApiClientKey } from '../common/config'; +import { DatasetQualityApiError } from '../common/dataset_quality_api_supertest'; +import { FtrProviderContext } from '../common/ftr_provider_context'; +import { expectToReject } from '../utils'; + +export default function ApiTest({ getService }: FtrProviderContext) { + const registry = getService('registry'); + const datasetQualityApiClient = getService('datasetQualityApiClient'); + + async function callApiAs(user: DatasetQualityApiClientKey) { + return await datasetQualityApiClient[user]({ + endpoint: 'GET /internal/dataset_quality/data_streams/stats', + params: { + query: { + type: 'logs', + sortOrder: 'asc', + }, + }, + }); + } + + registry.when('Api Key privileges check', { config: 'basic' }, () => { + describe('when missing required privileges', () => { + it('fails with a 500 error', async () => { + const err = await expectToReject( + async () => await callApiAs('readUser') + ); + + expect(err.res.status).to.be(500); + expect(err.res.body.message).to.contain('unauthorized'); + }); + }); + + describe('when required privileges are set', () => { + it('returns true when user has logMonitoring privileges', async () => { + const privileges = await callApiAs('datasetQualityLogsUser'); + + expect(privileges.body.items.length).to.be(0); + }); + }); + }); +} diff --git a/x-pack/test/dataset_quality_api_integration/tests/index.ts b/x-pack/test/dataset_quality_api_integration/tests/index.ts new file mode 100644 index 0000000000000..9aacc08923348 --- /dev/null +++ b/x-pack/test/dataset_quality_api_integration/tests/index.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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import globby from 'globby'; +import path from 'path'; +import { FtrProviderContext } from '../common/ftr_provider_context'; + +const cwd = path.join(__dirname); +const envGrepFiles = process.env.DATASET_QUALITY_TEST_GREP_FILES as string; + +function getGlobPattern() { + try { + const envGrepFilesParsed = JSON.parse(envGrepFiles as string) as string[]; + return envGrepFilesParsed.map((pattern) => `**/${pattern}**`); + } catch (e) { + // ignore + } + return '**/*.spec.ts'; +} + +export default function datasetQualityApiIntegrationTests({ + getService, + loadTestFile, +}: FtrProviderContext) { + const registry = getService('registry'); + + describe('Dataset quality API tests', function () { + const filePattern = getGlobPattern(); + const tests = globby.sync(filePattern, { cwd }); + + if (envGrepFiles) { + // eslint-disable-next-line no-console + console.log( + `\nCommand "--grep-files=${filePattern}" matched ${tests.length} file(s):\n${tests + .map((name) => ` - ${name}`) + .join('\n')}\n` + ); + } + + tests.forEach((testName) => { + describe(testName, () => { + loadTestFile(require.resolve(`./${testName}`)); + registry.run(); + }); + }); + }); +} diff --git a/x-pack/plugins/reporting/common/constants/job_types.ts b/x-pack/test/dataset_quality_api_integration/utils/expect_to_reject.ts similarity index 50% rename from x-pack/plugins/reporting/common/constants/job_types.ts rename to x-pack/test/dataset_quality_api_integration/utils/expect_to_reject.ts index b11391d81fa14..ae352c31d71a2 100644 --- a/x-pack/plugins/reporting/common/constants/job_types.ts +++ b/x-pack/test/dataset_quality_api_integration/utils/expect_to_reject.ts @@ -5,10 +5,13 @@ * 2.0. */ -export const CSV_JOB_TYPE = 'csv_searchsource'; +export async function expectToReject(fn: () => Promise): Promise { + let res: any; + try { + res = await fn(); + } catch (e) { + return e; + } -export const PDF_JOB_TYPE = 'printable_pdf'; -export const PDF_JOB_TYPE_V2 = 'printable_pdf_v2'; - -export const PNG_JOB_TYPE = 'PNG'; -export const PNG_JOB_TYPE_V2 = 'PNGV2'; + throw new Error(`expectToReject resolved: "${JSON.stringify(res)}"`); +} diff --git a/x-pack/test/dataset_quality_api_integration/utils/index.ts b/x-pack/test/dataset_quality_api_integration/utils/index.ts new file mode 100644 index 0000000000000..ae42a0d359d0b --- /dev/null +++ b/x-pack/test/dataset_quality_api_integration/utils/index.ts @@ -0,0 +1,10 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export { joinByKey } from './join_by_key'; +export { maybe } from './maybe'; +export { expectToReject } from './expect_to_reject'; diff --git a/x-pack/test/dataset_quality_api_integration/utils/join_by_key.ts b/x-pack/test/dataset_quality_api_integration/utils/join_by_key.ts new file mode 100644 index 0000000000000..0a74a2b94f393 --- /dev/null +++ b/x-pack/test/dataset_quality_api_integration/utils/join_by_key.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. + */ + +import { UnionToIntersection, ValuesType } from 'utility-types'; +import { isEqual, pull, merge, castArray } from 'lodash'; + +/** + * Joins a list of records by a given key. Key can be any type of value, from + * strings to plain objects, as long as it is present in all records. `isEqual` + * is used for comparing keys. + * + * UnionToIntersection is needed to get all keys of union types, see below for + * example. + * + */ + +export type JoinedReturnType< + T extends Record, + U extends UnionToIntersection +> = Array< + Partial & { + [k in keyof T]: T[k]; + } +>; + +type ArrayOrSingle = T | T[]; + +export function joinByKey< + T extends Record, + U extends UnionToIntersection, + V extends ArrayOrSingle +>(items: T[], key: V): JoinedReturnType; + +export function joinByKey< + T extends Record, + U extends UnionToIntersection, + V extends ArrayOrSingle, + W extends JoinedReturnType, + X extends (a: T, b: T) => ValuesType +>(items: T[], key: V, mergeFn: X): W; + +export function joinByKey( + items: Array>, + key: string | string[], + mergeFn: Function = (a: Record, b: Record) => merge({}, a, b) +) { + const keys = castArray(key); + return items.reduce>>((prev, current) => { + let item = prev.find((prevItem) => keys.every((k) => isEqual(prevItem[k], current[k]))); + + if (!item) { + item = { ...current }; + prev.push(item); + } else { + pull(prev, item).push(mergeFn(item, current)); + } + + return prev; + }, []); +} diff --git a/x-pack/plugins/reporting/server/export_types/printable_pdf/index.ts b/x-pack/test/dataset_quality_api_integration/utils/maybe.ts similarity index 76% rename from x-pack/plugins/reporting/server/export_types/printable_pdf/index.ts rename to x-pack/test/dataset_quality_api_integration/utils/maybe.ts index 39f055c707db1..f73dbe09d6ad4 100644 --- a/x-pack/plugins/reporting/server/export_types/printable_pdf/index.ts +++ b/x-pack/test/dataset_quality_api_integration/utils/maybe.ts @@ -5,4 +5,6 @@ * 2.0. */ -export { PdfV1ExportType } from './printable_pdf'; +export function maybe(value: T): T | null | undefined { + return value; +} diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/group1/index.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/group1/index.ts index 44d912f3271c6..d3e83305ad11e 100644 --- a/x-pack/test/detection_engine_api_integration/security_and_spaces/group1/index.ts +++ b/x-pack/test/detection_engine_api_integration/security_and_spaces/group1/index.ts @@ -14,7 +14,6 @@ export default ({ loadTestFile }: FtrProviderContext): void => { // action migration code. We are monitoring legacy action telemetry to clean up once we see their // existence being near 0. - loadTestFile(require.resolve('./check_privileges')); loadTestFile(require.resolve('./create_rules_bulk')); loadTestFile(require.resolve('./delete_rules')); loadTestFile(require.resolve('./delete_rules_bulk')); diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/group10/index.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/group10/index.ts index ae0bfaa8940e8..70b50d7f5aef3 100644 --- a/x-pack/test/detection_engine_api_integration/security_and_spaces/group10/index.ts +++ b/x-pack/test/detection_engine_api_integration/security_and_spaces/group10/index.ts @@ -25,10 +25,5 @@ export default ({ loadTestFile }: FtrProviderContext): void => { loadTestFile(require.resolve('./perform_bulk_action')); loadTestFile(require.resolve('./perform_bulk_action_dry_run')); loadTestFile(require.resolve('./patch_rules')); - loadTestFile(require.resolve('./read_privileges')); - loadTestFile(require.resolve('./timestamps')); - loadTestFile(require.resolve('./runtime')); - loadTestFile(require.resolve('./throttle')); - loadTestFile(require.resolve('./ignore_fields')); }); }; diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/group4/config.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/group4/config.ts deleted file mode 100644 index 2430b8f2148d9..0000000000000 --- a/x-pack/test/detection_engine_api_integration/security_and_spaces/group4/config.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 { FtrConfigProviderContext } from '@kbn/test'; - -// eslint-disable-next-line import/no-default-export -export default async function ({ readConfigFile }: FtrConfigProviderContext) { - const functionalConfig = await readConfigFile(require.resolve('../config.base.ts')); - - return { - ...functionalConfig.getAll(), - testFiles: [require.resolve('.')], - }; -} diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/rule_execution_logic/mocks/new_terms.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/rule_execution_logic/mocks/new_terms.ts deleted file mode 100644 index 15c63546a4be7..0000000000000 --- a/x-pack/test/detection_engine_api_integration/security_and_spaces/rule_execution_logic/mocks/new_terms.ts +++ /dev/null @@ -1,1409 +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 const largeArraysBuckets = [ - { - key: { - large_array_20: 'value-of-20-0', - large_array_10: 'value-of-10-0', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-1', - large_array_10: 'value-of-10-0', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-2', - large_array_10: 'value-of-10-0', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-3', - large_array_10: 'value-of-10-0', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-4', - large_array_10: 'value-of-10-0', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-5', - large_array_10: 'value-of-10-0', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-6', - large_array_10: 'value-of-10-0', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-7', - large_array_10: 'value-of-10-0', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-8', - large_array_10: 'value-of-10-0', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-9', - large_array_10: 'value-of-10-0', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-10', - large_array_10: 'value-of-10-0', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-11', - large_array_10: 'value-of-10-0', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-12', - large_array_10: 'value-of-10-0', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-13', - large_array_10: 'value-of-10-0', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-14', - large_array_10: 'value-of-10-0', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-15', - large_array_10: 'value-of-10-0', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-16', - large_array_10: 'value-of-10-0', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-17', - large_array_10: 'value-of-10-0', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-18', - large_array_10: 'value-of-10-0', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-19', - large_array_10: 'value-of-10-0', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-0', - large_array_10: 'value-of-10-1', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-1', - large_array_10: 'value-of-10-1', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-2', - large_array_10: 'value-of-10-1', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-3', - large_array_10: 'value-of-10-1', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-4', - large_array_10: 'value-of-10-1', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-5', - large_array_10: 'value-of-10-1', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-6', - large_array_10: 'value-of-10-1', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-7', - large_array_10: 'value-of-10-1', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-8', - large_array_10: 'value-of-10-1', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-9', - large_array_10: 'value-of-10-1', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-10', - large_array_10: 'value-of-10-1', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-11', - large_array_10: 'value-of-10-1', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-12', - large_array_10: 'value-of-10-1', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-13', - large_array_10: 'value-of-10-1', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-14', - large_array_10: 'value-of-10-1', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-15', - large_array_10: 'value-of-10-1', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-16', - large_array_10: 'value-of-10-1', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-17', - large_array_10: 'value-of-10-1', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-18', - large_array_10: 'value-of-10-1', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-19', - large_array_10: 'value-of-10-1', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-0', - large_array_10: 'value-of-10-2', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-1', - large_array_10: 'value-of-10-2', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-2', - large_array_10: 'value-of-10-2', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-3', - large_array_10: 'value-of-10-2', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-4', - large_array_10: 'value-of-10-2', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-5', - large_array_10: 'value-of-10-2', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-6', - large_array_10: 'value-of-10-2', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-7', - large_array_10: 'value-of-10-2', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-8', - large_array_10: 'value-of-10-2', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-9', - large_array_10: 'value-of-10-2', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-10', - large_array_10: 'value-of-10-2', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-11', - large_array_10: 'value-of-10-2', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-12', - large_array_10: 'value-of-10-2', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-13', - large_array_10: 'value-of-10-2', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-14', - large_array_10: 'value-of-10-2', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-15', - large_array_10: 'value-of-10-2', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-16', - large_array_10: 'value-of-10-2', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-17', - large_array_10: 'value-of-10-2', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-18', - large_array_10: 'value-of-10-2', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-19', - large_array_10: 'value-of-10-2', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-0', - large_array_10: 'value-of-10-3', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-1', - large_array_10: 'value-of-10-3', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-2', - large_array_10: 'value-of-10-3', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-3', - large_array_10: 'value-of-10-3', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-4', - large_array_10: 'value-of-10-3', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-5', - large_array_10: 'value-of-10-3', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-6', - large_array_10: 'value-of-10-3', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-7', - large_array_10: 'value-of-10-3', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-8', - large_array_10: 'value-of-10-3', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-9', - large_array_10: 'value-of-10-3', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-10', - large_array_10: 'value-of-10-3', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-11', - large_array_10: 'value-of-10-3', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-12', - large_array_10: 'value-of-10-3', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-13', - large_array_10: 'value-of-10-3', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-14', - large_array_10: 'value-of-10-3', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-15', - large_array_10: 'value-of-10-3', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-16', - large_array_10: 'value-of-10-3', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-17', - large_array_10: 'value-of-10-3', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-18', - large_array_10: 'value-of-10-3', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-19', - large_array_10: 'value-of-10-3', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-0', - large_array_10: 'value-of-10-4', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-1', - large_array_10: 'value-of-10-4', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-2', - large_array_10: 'value-of-10-4', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-3', - large_array_10: 'value-of-10-4', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-4', - large_array_10: 'value-of-10-4', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-5', - large_array_10: 'value-of-10-4', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-6', - large_array_10: 'value-of-10-4', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-7', - large_array_10: 'value-of-10-4', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-8', - large_array_10: 'value-of-10-4', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-9', - large_array_10: 'value-of-10-4', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-10', - large_array_10: 'value-of-10-4', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-11', - large_array_10: 'value-of-10-4', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-12', - large_array_10: 'value-of-10-4', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-13', - large_array_10: 'value-of-10-4', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-14', - large_array_10: 'value-of-10-4', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-15', - large_array_10: 'value-of-10-4', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-16', - large_array_10: 'value-of-10-4', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-17', - large_array_10: 'value-of-10-4', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-18', - large_array_10: 'value-of-10-4', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-19', - large_array_10: 'value-of-10-4', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-0', - large_array_10: 'value-of-10-5', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-1', - large_array_10: 'value-of-10-5', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-2', - large_array_10: 'value-of-10-5', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-3', - large_array_10: 'value-of-10-5', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-4', - large_array_10: 'value-of-10-5', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-5', - large_array_10: 'value-of-10-5', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-6', - large_array_10: 'value-of-10-5', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-7', - large_array_10: 'value-of-10-5', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-8', - large_array_10: 'value-of-10-5', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-9', - large_array_10: 'value-of-10-5', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-10', - large_array_10: 'value-of-10-5', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-11', - large_array_10: 'value-of-10-5', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-12', - large_array_10: 'value-of-10-5', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-13', - large_array_10: 'value-of-10-5', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-14', - large_array_10: 'value-of-10-5', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-15', - large_array_10: 'value-of-10-5', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-16', - large_array_10: 'value-of-10-5', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-17', - large_array_10: 'value-of-10-5', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-18', - large_array_10: 'value-of-10-5', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-19', - large_array_10: 'value-of-10-5', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-0', - large_array_10: 'value-of-10-6', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-1', - large_array_10: 'value-of-10-6', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-2', - large_array_10: 'value-of-10-6', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-3', - large_array_10: 'value-of-10-6', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-4', - large_array_10: 'value-of-10-6', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-5', - large_array_10: 'value-of-10-6', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-6', - large_array_10: 'value-of-10-6', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-7', - large_array_10: 'value-of-10-6', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-8', - large_array_10: 'value-of-10-6', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-9', - large_array_10: 'value-of-10-6', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-10', - large_array_10: 'value-of-10-6', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-11', - large_array_10: 'value-of-10-6', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-12', - large_array_10: 'value-of-10-6', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-13', - large_array_10: 'value-of-10-6', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-14', - large_array_10: 'value-of-10-6', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-15', - large_array_10: 'value-of-10-6', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-16', - large_array_10: 'value-of-10-6', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-17', - large_array_10: 'value-of-10-6', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-18', - large_array_10: 'value-of-10-6', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-19', - large_array_10: 'value-of-10-6', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-0', - large_array_10: 'value-of-10-7', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-1', - large_array_10: 'value-of-10-7', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-2', - large_array_10: 'value-of-10-7', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-3', - large_array_10: 'value-of-10-7', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-4', - large_array_10: 'value-of-10-7', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-5', - large_array_10: 'value-of-10-7', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-6', - large_array_10: 'value-of-10-7', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-7', - large_array_10: 'value-of-10-7', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-8', - large_array_10: 'value-of-10-7', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-9', - large_array_10: 'value-of-10-7', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-10', - large_array_10: 'value-of-10-7', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-11', - large_array_10: 'value-of-10-7', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-12', - large_array_10: 'value-of-10-7', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-13', - large_array_10: 'value-of-10-7', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-14', - large_array_10: 'value-of-10-7', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-15', - large_array_10: 'value-of-10-7', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-16', - large_array_10: 'value-of-10-7', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-17', - large_array_10: 'value-of-10-7', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-18', - large_array_10: 'value-of-10-7', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-19', - large_array_10: 'value-of-10-7', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-0', - large_array_10: 'value-of-10-8', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-1', - large_array_10: 'value-of-10-8', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-2', - large_array_10: 'value-of-10-8', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-3', - large_array_10: 'value-of-10-8', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-4', - large_array_10: 'value-of-10-8', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-5', - large_array_10: 'value-of-10-8', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-6', - large_array_10: 'value-of-10-8', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-7', - large_array_10: 'value-of-10-8', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-8', - large_array_10: 'value-of-10-8', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-9', - large_array_10: 'value-of-10-8', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-10', - large_array_10: 'value-of-10-8', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-11', - large_array_10: 'value-of-10-8', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-12', - large_array_10: 'value-of-10-8', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-13', - large_array_10: 'value-of-10-8', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-14', - large_array_10: 'value-of-10-8', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-15', - large_array_10: 'value-of-10-8', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-16', - large_array_10: 'value-of-10-8', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-17', - large_array_10: 'value-of-10-8', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-18', - large_array_10: 'value-of-10-8', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-19', - large_array_10: 'value-of-10-8', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-0', - large_array_10: 'value-of-10-9', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-1', - large_array_10: 'value-of-10-9', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-2', - large_array_10: 'value-of-10-9', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-3', - large_array_10: 'value-of-10-9', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-4', - large_array_10: 'value-of-10-9', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-5', - large_array_10: 'value-of-10-9', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-6', - large_array_10: 'value-of-10-9', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-7', - large_array_10: 'value-of-10-9', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-8', - large_array_10: 'value-of-10-9', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-9', - large_array_10: 'value-of-10-9', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-10', - large_array_10: 'value-of-10-9', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-11', - large_array_10: 'value-of-10-9', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-12', - large_array_10: 'value-of-10-9', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-13', - large_array_10: 'value-of-10-9', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-14', - large_array_10: 'value-of-10-9', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-15', - large_array_10: 'value-of-10-9', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-16', - large_array_10: 'value-of-10-9', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-17', - large_array_10: 'value-of-10-9', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-18', - large_array_10: 'value-of-10-9', - }, - doc_count: 1, - }, - { - key: { - large_array_20: 'value-of-20-19', - large_array_10: 'value-of-10-9', - }, - doc_count: 1, - }, -]; diff --git a/x-pack/test/detection_engine_api_integration/utils/create_new_action.ts b/x-pack/test/detection_engine_api_integration/utils/create_new_action.ts deleted file mode 100644 index d5093d8d5d39b..0000000000000 --- a/x-pack/test/detection_engine_api_integration/utils/create_new_action.ts +++ /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; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import type { ToolingLog } from '@kbn/tooling-log'; -import type SuperTest from 'supertest'; - -import { getWebHookAction } from './get_web_hook_action'; - -/** - * Helper to cut down on the noise in some of the tests. This - * creates a new action and expects a 200 and does not do any retries. - * @param supertest The supertest deps - */ -export const createNewAction = async ( - supertest: SuperTest.SuperTest, - log: ToolingLog -) => { - const response = await supertest - .post('/api/actions/action') - .set('kbn-xsrf', 'true') - .send(getWebHookAction()); - if (response.status !== 200) { - log.error( - `Did not get an expected 200 "ok" when creating a new action. CI issues could happen. Suspect this line if you are seeing CI issues. body: ${JSON.stringify( - response.body - )}, status: ${JSON.stringify(response.status)}` - ); - } - return response.body; -}; diff --git a/x-pack/test/detection_engine_api_integration/utils/index.ts b/x-pack/test/detection_engine_api_integration/utils/index.ts index 1c62f3dc2c123..a1373f03a1817 100644 --- a/x-pack/test/detection_engine_api_integration/utils/index.ts +++ b/x-pack/test/detection_engine_api_integration/utils/index.ts @@ -13,9 +13,7 @@ export * from './create_container_with_entries'; export * from './create_exception_list'; export * from './create_exception_list_item'; export * from './create_legacy_rule_action'; -export * from './create_new_action'; export * from './create_rule'; -export * from './create_rule_with_auth'; export * from './create_rule_with_exception_entries'; export * from './create_rule_saved_object'; export * from './create_signals_index'; @@ -26,12 +24,10 @@ export * from './delete_all_alerts'; export * from './delete_all_timelines'; export * from './delete_exception_list'; export * from './delete_rule'; -export * from './downgrade_immutable_rule'; export * from './finalize_signals_migration'; export * from './find_immutable_rule_by_id'; export * from './get_complex_rule'; export * from './get_complex_rule_output'; -export * from './get_detection_metrics_from_body'; export * from './get_eql_rule_for_signal_testing'; export * from './get_event_log_execute_complete_by_id'; export * from './get_legacy_action_notification_so'; @@ -48,7 +44,6 @@ export * from './get_rule_for_signal_testing_with_timestamp_override'; export * from './get_rule_with_web_hook_action'; export * from './get_rule_with_legacy_investigation_fields'; export * from './get_saved_query_rule_for_signal_testing'; -export * from './get_security_telemetry_stats'; export * from './get_signal_status'; export * from './get_signals_by_id'; export * from './get_signals_by_ids'; @@ -63,9 +58,6 @@ export * from './get_simple_rule_output_without_rule_id'; export * from './get_simple_rule_update'; export * from './get_simple_rule_without_rule_id'; export * from './get_simple_saved_query_rule'; -export * from './get_simple_threat_match'; -export * from './get_stats'; -export * from './get_stats_url'; export * from './get_threat_match_rule_for_signal_testing'; export * from './get_threshold_rule_for_signal_testing'; export * from './get_slack_action'; @@ -77,7 +69,6 @@ export * from './preview_rule_with_exception_entries'; export * from './preview_rule'; export * from './refresh_index'; export * from './route_with_namespace'; -export * from './remove_time_fields_from_telemetry_stats'; export * from './remove_server_generated_properties'; export * from './remove_server_generated_properties_including_rule_id'; export * from './resolve_simple_rule_output'; diff --git a/x-pack/test/encrypted_saved_objects_api_integration/plugins/api_consumer_plugin/server/index.ts b/x-pack/test/encrypted_saved_objects_api_integration/plugins/api_consumer_plugin/server/index.ts index fec7965b88df4..c7d14986b6a14 100644 --- a/x-pack/test/encrypted_saved_objects_api_integration/plugins/api_consumer_plugin/server/index.ts +++ b/x-pack/test/encrypted_saved_objects_api_integration/plugins/api_consumer_plugin/server/index.ts @@ -48,7 +48,7 @@ export interface PluginsStart { spaces: never; } -export const plugin: PluginInitializer = () => ({ +export const plugin: PluginInitializer = async () => ({ setup(core: CoreSetup, deps: PluginsSetup) { for (const [name, namespaceType, hidden] of [ [SAVED_OBJECT_WITH_SECRET_TYPE, 'single', false], diff --git a/x-pack/test/fleet_api_integration/apis/agents/upgrade.ts b/x-pack/test/fleet_api_integration/apis/agents/upgrade.ts index 0a3dc09692b68..3d48d66957191 100644 --- a/x-pack/test/fleet_api_integration/apis/agents/upgrade.ts +++ b/x-pack/test/fleet_api_integration/apis/agents/upgrade.ts @@ -443,6 +443,167 @@ export default function (providerContext: FtrProviderContext) { }) .expect(200); }); + + it('should respond 400 if trying to upgrade an already upgrading agent with no upgrade details', async () => { + await es.update({ + id: 'agent1', + refresh: 'wait_for', + index: AGENTS_INDEX, + body: { + doc: { + upgrade_started_at: new Date(Date.now() - 9 * 6e4).toISOString(), + local_metadata: { + elastic: { + agent: { + upgradeable: true, + version: '0.0.0', + }, + }, + }, + }, + }, + }); + const response = await supertest + .post(`/api/fleet/agents/agent1/upgrade`) + .set('kbn-xsrf', 'xxx') + .send({ + version: fleetServerVersion, + }) + .expect(400); + + expect(response.body.message).to.contain('is already upgrading'); + }); + + it('should respond 200 if trying to upgrade an already upgrading agent with no upgrade details with force flag', async () => { + await es.update({ + id: 'agent1', + refresh: 'wait_for', + index: AGENTS_INDEX, + body: { + doc: { + upgrade_started_at: new Date(Date.now() - 9 * 6e4).toISOString(), + local_metadata: { + elastic: { + agent: { + upgradeable: true, + version: '0.0.0', + }, + }, + }, + }, + }, + }); + await supertest + .post(`/api/fleet/agents/agent1/upgrade`) + .set('kbn-xsrf', 'xxx') + .send({ + version: fleetServerVersion, + force: true, + }) + .expect(200); + }); + + it('should respond 400 if trying to upgrade an already upgrading agent with upgrade details', async () => { + await es.update({ + id: 'agent1', + refresh: 'wait_for', + index: AGENTS_INDEX, + body: { + doc: { + local_metadata: { + elastic: { + agent: { + upgradeable: true, + version: '0.0.0', + }, + }, + }, + upgrade_details: { + target_version: fleetServerVersion, + action_id: 'XXX', + state: 'UPG_REQUESTED', + }, + }, + }, + }); + const response = await supertest + .post(`/api/fleet/agents/agent1/upgrade`) + .set('kbn-xsrf', 'xxx') + .send({ + version: fleetServerVersion, + }) + .expect(400); + + expect(response.body.message).to.contain('is already upgrading'); + }); + + it('should respond 200 if trying to upgrade an already upgrading agent with upgrade details with force flag', async () => { + await es.update({ + id: 'agent1', + refresh: 'wait_for', + index: AGENTS_INDEX, + body: { + doc: { + local_metadata: { + elastic: { + agent: { + upgradeable: true, + version: '0.0.0', + }, + }, + }, + upgrade_details: { + target_version: fleetServerVersion, + action_id: 'XXX', + state: 'UPG_REQUESTED', + }, + }, + }, + }); + await supertest + .post(`/api/fleet/agents/agent1/upgrade`) + .set('kbn-xsrf', 'xxx') + .send({ + version: fleetServerVersion, + force: true, + }) + .expect(200); + }); + + it('should respond 200 if trying to upgrade an agent with a failed upgrade status', async () => { + await es.update({ + id: 'agent1', + refresh: 'wait_for', + index: AGENTS_INDEX, + body: { + doc: { + local_metadata: { + elastic: { + agent: { + upgradeable: true, + version: '0.0.0', + }, + }, + }, + upgrade_details: { + target_version: fleetServerVersion, + action_id: 'XXX', + state: 'UPG_FAILED', + metadata: { + error_msg: 'Upgrade timed out', + }, + }, + }, + }, + }); + await supertest + .post(`/api/fleet/agents/agent1/upgrade`) + .set('kbn-xsrf', 'xxx') + .send({ + version: fleetServerVersion, + }) + .expect(200); + }); }); describe('multiple agents', () => { @@ -1291,6 +1452,61 @@ export default function (providerContext: FtrProviderContext) { expect(typeof agent1data.body.item.upgrade_started_at).to.be('string'); expect(typeof agent2data.body.item.upgrade_started_at).to.be('string'); }); + + it('should set a long expiration time when the start_time is set to now (immediate rollout period)', async () => { + await es.update({ + id: 'agent1', + refresh: 'wait_for', + index: AGENTS_INDEX, + body: { + doc: { + local_metadata: { elastic: { agent: { upgradeable: true, version: '0.0.0' } } }, + }, + }, + }); + await es.update({ + id: 'agent2', + refresh: 'wait_for', + index: AGENTS_INDEX, + body: { + doc: { + local_metadata: { elastic: { agent: { upgradeable: true, version: '0.0.0' } } }, + }, + }, + }); + await supertest + .post(`/api/fleet/agents/bulk_upgrade`) + .set('kbn-xsrf', 'xxx') + .send({ + version: fleetServerVersion, + agents: ['agent1', 'agent2'], + start_time: new Date(Date.now()).toISOString(), + }) + .expect(200); + + const actionsRes = await es.search({ + index: '.fleet-actions', + body: { + sort: [{ '@timestamp': { order: 'desc' } }], + }, + }); + + const action: any = actionsRes.hits.hits[0]._source; + expect(action).to.have.keys( + 'agents', + 'start_time', + 'minimum_execution_duration', + 'expiration' + ); + // calculate 1 month from now + const today = new Date(); + const nextMonthUnixTime = today.setMonth(today.getMonth() + 1); + const nextMonth = new Date(nextMonthUnixTime).toISOString().slice(0, 10); + + expect(action.expiration).contain(`${nextMonth}`); + expect(action.agents).contain('agent1'); + expect(action.agents).contain('agent2'); + }); }); }); } diff --git a/x-pack/test/fleet_api_integration/apis/epm/get.ts b/x-pack/test/fleet_api_integration/apis/epm/get.ts index 2ca984ceb67dd..045a6d034a0a0 100644 --- a/x-pack/test/fleet_api_integration/apis/epm/get.ts +++ b/x-pack/test/fleet_api_integration/apis/epm/get.ts @@ -38,7 +38,8 @@ export default function (providerContext: FtrProviderContext) { '../fixtures/direct_upload_packages/apache_0.1.4.zip' ); - describe('EPM - get', () => { + // FLAKY: https://github.com/elastic/kibana/issues/163203 + describe.skip('EPM - get', () => { skipIfNoDockerRegistry(providerContext); setupFleetAndAgents(providerContext); diff --git a/x-pack/test/functional/apps/infra/logs/log_stream_date_nano.ts b/x-pack/test/functional/apps/infra/logs/log_stream_date_nano.ts index e2bbdc8d35ce6..f01e5fd0a06f5 100644 --- a/x-pack/test/functional/apps/infra/logs/log_stream_date_nano.ts +++ b/x-pack/test/functional/apps/infra/logs/log_stream_date_nano.ts @@ -67,8 +67,8 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { const currentUrl = await browser.getCurrentUrl(); const parsedUrl = new URL(currentUrl); - expect(parsedUrl.searchParams.get('logPosition')).to.be( - `(position:(tiebreaker:3,time:\'2018-10-17T19:46:22.333333333Z\'))` + expect(parsedUrl.searchParams.get('logPosition')).to.contain( + `time:\'2018-10-17T19:46:22.333333333Z\'` ); }); diff --git a/x-pack/test/functional/apps/maps/group1/blended_vector_layer.js b/x-pack/test/functional/apps/maps/group1/blended_vector_layer.js index 28a68edf0e75c..d142513dfd4a9 100644 --- a/x-pack/test/functional/apps/maps/group1/blended_vector_layer.js +++ b/x-pack/test/functional/apps/maps/group1/blended_vector_layer.js @@ -13,6 +13,9 @@ export default function ({ getPageObjects, getService }) { const security = getService('security'); describe('blended vector layer', () => { + const LOAD_DOCUMENTS_REQUEST_NAME = 'load layer features (logstash-*)'; + const LOAD_CLUSTERS_REQUEST_NAME = 'load layer features (Clustered logstash-*)'; + before(async () => { await security.testUser.setRoles(['test_logstash_reader', 'global_maps_all']); await PageObjects.maps.loadSavedMap('blended document example'); @@ -27,20 +30,26 @@ export default function ({ getPageObjects, getService }) { }); it('should request documents when zoomed to smaller regions showing less data', async () => { - const { rawResponse: response } = await PageObjects.maps.getResponse(); + const { rawResponse: response } = await PageObjects.maps.getResponse( + LOAD_DOCUMENTS_REQUEST_NAME + ); // Allow a range of hits to account for variances in browser window size. expect(response.hits.hits.length).to.be.within(5, 12); }); it('should request clusters when zoomed to larger regions showing lots of data', async () => { await PageObjects.maps.setView(20, -90, 2); - const { rawResponse: response } = await PageObjects.maps.getResponse(); + const { rawResponse: response } = await PageObjects.maps.getResponse( + LOAD_CLUSTERS_REQUEST_NAME + ); expect(response.aggregations.gridSplit.buckets.length).to.equal(15); }); it('should request documents when query narrows data', async () => { await PageObjects.maps.setAndSubmitQuery('bytes > 19000'); - const { rawResponse: response } = await PageObjects.maps.getResponse(); + const { rawResponse: response } = await PageObjects.maps.getResponse( + LOAD_DOCUMENTS_REQUEST_NAME + ); expect(response.hits.hits.length).to.equal(75); }); }); diff --git a/x-pack/test/functional/apps/maps/group2/embeddable/dashboard.js b/x-pack/test/functional/apps/maps/group2/embeddable/dashboard.js index 2750bf3a7f68d..bdc681e06eece 100644 --- a/x-pack/test/functional/apps/maps/group2/embeddable/dashboard.js +++ b/x-pack/test/functional/apps/maps/group2/embeddable/dashboard.js @@ -77,7 +77,7 @@ export default function ({ getPageObjects, getService }) { await retry.try(async () => { const joinExampleRequestNames = await inspector.getRequestNames(); expect(joinExampleRequestNames).to.equal( - 'geo_shapes* documents request,geo_shapes* term join request' + 'load layer features (geo_shapes*),load join metrics (geo_shapes*)' ); }); await inspector.close(); @@ -88,7 +88,7 @@ export default function ({ getPageObjects, getService }) { await inspector.close(); expect(singleExampleRequest).to.be(true); - expect(selectedExampleRequest).to.equal('logstash-* grid request'); + expect(selectedExampleRequest).to.equal('load layer features (logstash-*)'); }); it('should apply container state (time, query, filters) to embeddable when loaded', async () => { @@ -120,7 +120,7 @@ export default function ({ getPageObjects, getService }) { const { rawResponse: joinResponse } = await PageObjects.maps.getResponseFromDashboardPanel( 'join example', - 'geo_shapes* term join request' + 'load join metrics (geo_shapes*)' ); expect(joinResponse.aggregations.join.buckets.length).to.equal(1); }); diff --git a/x-pack/test/functional/apps/maps/group4/joins.js b/x-pack/test/functional/apps/maps/group4/joins.js index bf1304e3f3470..74e68cb12c11a 100644 --- a/x-pack/test/functional/apps/maps/group4/joins.js +++ b/x-pack/test/functional/apps/maps/group4/joins.js @@ -39,7 +39,7 @@ export default function ({ getPageObjects, getService }) { it('should re-fetch join with refresh timer', async () => { async function getRequestTimestamp() { - await PageObjects.maps.openInspectorRequest('geo_shapes* term join request'); + await PageObjects.maps.openInspectorRequest('load join metrics (geo_shapes*)'); const requestStats = await inspector.getTableData(); const requestTimestamp = PageObjects.maps.getInspectorStatRowHit( requestStats, @@ -122,7 +122,7 @@ export default function ({ getPageObjects, getService }) { it('should not apply query to source and apply query to join', async () => { const { rawResponse: joinResponse } = await PageObjects.maps.getResponse( - 'geo_shapes* term join request' + 'load join metrics (geo_shapes*)' ); expect(joinResponse.aggregations.join.buckets.length).to.equal(2); }); @@ -139,7 +139,7 @@ export default function ({ getPageObjects, getService }) { it('should apply query to join request', async () => { const { rawResponse: joinResponse } = await PageObjects.maps.getResponse( - 'geo_shapes* term join request' + 'load join metrics (geo_shapes*)' ); expect(joinResponse.aggregations.join.buckets.length).to.equal(1); }); diff --git a/x-pack/test/functional/apps/observability_log_explorer/app.ts b/x-pack/test/functional/apps/observability_log_explorer/app.ts index 26fb9b4e8d19e..c60bf38205e3a 100644 --- a/x-pack/test/functional/apps/observability_log_explorer/app.ts +++ b/x-pack/test/functional/apps/observability_log_explorer/app.ts @@ -5,11 +5,14 @@ * 2.0. */ import expect from '@kbn/expect'; -import { FtrProviderContext } from '../../ftr_provider_context'; +import { log, timerange } from '@kbn/apm-synthtrace-client'; +import { FtrProviderContext } from './config'; export default function ({ getService, getPageObjects }: FtrProviderContext) { const PageObjects = getPageObjects(['common', 'navigationalSearch', 'observabilityLogExplorer']); const testSubjects = getService('testSubjects'); + const synthtrace = getService('logSynthtraceEsClient'); + const dataGrid = getService('dataGrid'); describe('Application', () => { it('is shown in the global search', async () => { @@ -24,5 +27,32 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await PageObjects.observabilityLogExplorer.navigateTo(); await testSubjects.existOrFail('observability-nav-observability-log-explorer-explorer'); }); + + it('should load logs', async () => { + const from = '2023-08-03T10:24:14.035Z'; + const to = '2023-08-03T10:24:14.091Z'; + const COUNT = 5; + await synthtrace.index(generateLogsData({ from, to, count: COUNT })); + await PageObjects.observabilityLogExplorer.navigateTo(); + const docCount = await dataGrid.getDocCount(); + + expect(docCount).to.be(COUNT); + await synthtrace.clean(); + }); }); } + +function generateLogsData({ from, to, count = 1 }: { from: string; to: string; count: number }) { + const range = timerange(from, to); + + return range + .interval('1m') + .rate(1) + .generator((timestamp) => + Array(count) + .fill(0) + .map(() => { + return log.create().message('A sample log').timestamp(timestamp); + }) + ); +} diff --git a/x-pack/test/functional/apps/observability_log_explorer/columns_selection.ts b/x-pack/test/functional/apps/observability_log_explorer/columns_selection.ts index 7738d3b97b2bc..b23fd6813c0f6 100644 --- a/x-pack/test/functional/apps/observability_log_explorer/columns_selection.ts +++ b/x-pack/test/functional/apps/observability_log_explorer/columns_selection.ts @@ -6,7 +6,7 @@ */ import expect from '@kbn/expect'; import rison from '@kbn/rison'; -import { FtrProviderContext } from '../../ftr_provider_context'; +import { FtrProviderContext } from './config'; const defaultLogColumns = ['@timestamp', 'service.name', 'host.name', 'message']; diff --git a/x-pack/test/functional/apps/observability_log_explorer/config.ts b/x-pack/test/functional/apps/observability_log_explorer/config.ts index d0d07ff200281..c94616d50e14b 100644 --- a/x-pack/test/functional/apps/observability_log_explorer/config.ts +++ b/x-pack/test/functional/apps/observability_log_explorer/config.ts @@ -5,13 +5,38 @@ * 2.0. */ -import { FtrConfigProviderContext } from '@kbn/test'; +import { FtrConfigProviderContext, GenericFtrProviderContext } from '@kbn/test'; +import { createLogger, LogLevel, LogsSynthtraceEsClient } from '@kbn/apm-synthtrace'; +import { FtrProviderContext as InheritedFtrProviderContext } from '../../ftr_provider_context'; -export default async function ({ readConfigFile }: FtrConfigProviderContext) { +export default async function createTestConfig({ readConfigFile }: FtrConfigProviderContext) { const functionalConfig = await readConfigFile(require.resolve('../../config.base.js')); + const services = functionalConfig.get('services'); + const pageObjects = functionalConfig.get('pageObjects'); return { ...functionalConfig.getAll(), testFiles: [require.resolve('.')], + services: { + ...services, + logSynthtraceEsClient: (context: InheritedFtrProviderContext) => { + return new LogsSynthtraceEsClient({ + client: context.getService('es'), + logger: createLogger(LogLevel.info), + refreshAfterIndex: true, + }); + }, + }, + pageObjects, }; } + +export type CreateTestConfig = Awaited>; + +export type ObsLogExplorerServices = CreateTestConfig['services']; +export type ObsLogExplorerPageObject = CreateTestConfig['pageObjects']; + +export type FtrProviderContext = GenericFtrProviderContext< + ObsLogExplorerServices, + ObsLogExplorerPageObject +>; diff --git a/x-pack/test/functional/apps/observability_log_explorer/dataset_selection_state.ts b/x-pack/test/functional/apps/observability_log_explorer/dataset_selection_state.ts index e232b9df5f1c4..9fc2cca312551 100644 --- a/x-pack/test/functional/apps/observability_log_explorer/dataset_selection_state.ts +++ b/x-pack/test/functional/apps/observability_log_explorer/dataset_selection_state.ts @@ -6,7 +6,7 @@ */ import expect from '@kbn/expect'; import rison from '@kbn/rison'; -import { FtrProviderContext } from '../../ftr_provider_context'; +import { FtrProviderContext } from './config'; export default function ({ getService, getPageObjects }: FtrProviderContext) { const browser = getService('browser'); diff --git a/x-pack/test/functional/apps/observability_log_explorer/dataset_selector.ts b/x-pack/test/functional/apps/observability_log_explorer/dataset_selector.ts index 73426c990ec48..d656301a13891 100644 --- a/x-pack/test/functional/apps/observability_log_explorer/dataset_selector.ts +++ b/x-pack/test/functional/apps/observability_log_explorer/dataset_selector.ts @@ -5,7 +5,8 @@ * 2.0. */ import expect from '@kbn/expect'; -import { FtrProviderContext } from '../../ftr_provider_context'; +import { FtrProviderContext } from './config'; +import { WebElementWrapper } from '../../../../../test/functional/services/lib/web_element_wrapper'; const initialPackageMap = { apache: 'Apache HTTP Server', @@ -101,7 +102,9 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { it('should display an empty prompt for no integrations', async () => { const menuEntries = await PageObjects.observabilityLogExplorer .getIntegrationsContextMenu() - .then((menu) => PageObjects.observabilityLogExplorer.getPanelEntries(menu)); + .then((menu: WebElementWrapper) => + PageObjects.observabilityLogExplorer.getPanelEntries(menu) + ); expect(menuEntries.length).to.be(0); await PageObjects.observabilityLogExplorer.assertListStatusEmptyPromptExistsWithTitle( @@ -161,7 +164,9 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { const uncategorizedEntries = await PageObjects.observabilityLogExplorer .getUncategorizedContextMenu() - .then((menu) => PageObjects.observabilityLogExplorer.getPanelEntries(menu)); + .then((menu: WebElementWrapper) => + PageObjects.observabilityLogExplorer.getPanelEntries(menu) + ); expect(uncategorizedEntries.length).to.be(0); @@ -313,7 +318,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { const [panelTitleNode, integrationDatasetEntries] = await PageObjects.observabilityLogExplorer .getIntegrationsContextMenu() - .then((menu) => + .then((menu: WebElementWrapper) => Promise.all([ PageObjects.observabilityLogExplorer.getPanelTitle(menu), PageObjects.observabilityLogExplorer.getPanelEntries(menu), @@ -335,7 +340,9 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await retry.try(async () => { const panelTitleNode = await PageObjects.observabilityLogExplorer .getIntegrationsContextMenu() - .then((menu) => PageObjects.observabilityLogExplorer.getPanelTitle(menu)); + .then((menu: WebElementWrapper) => + PageObjects.observabilityLogExplorer.getPanelTitle(menu) + ); expect(await panelTitleNode.getVisibleText()).to.be('Apache HTTP Server'); }); @@ -345,7 +352,9 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await retry.try(async () => { const menuEntries = await PageObjects.observabilityLogExplorer .getIntegrationsContextMenu() - .then((menu) => PageObjects.observabilityLogExplorer.getPanelEntries(menu)); + .then((menu: WebElementWrapper) => + PageObjects.observabilityLogExplorer.getPanelEntries(menu) + ); expect(await menuEntries[0].getVisibleText()).to.be('access'); expect(await menuEntries[1].getVisibleText()).to.be('error'); @@ -356,7 +365,9 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await retry.try(async () => { const menuEntries = await PageObjects.observabilityLogExplorer .getIntegrationsContextMenu() - .then((menu) => PageObjects.observabilityLogExplorer.getPanelEntries(menu)); + .then((menu: WebElementWrapper) => + PageObjects.observabilityLogExplorer.getPanelEntries(menu) + ); expect(await menuEntries[0].getVisibleText()).to.be('error'); expect(await menuEntries[1].getVisibleText()).to.be('access'); @@ -367,7 +378,9 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await retry.try(async () => { const menuEntries = await PageObjects.observabilityLogExplorer .getIntegrationsContextMenu() - .then((menu) => PageObjects.observabilityLogExplorer.getPanelEntries(menu)); + .then((menu: WebElementWrapper) => + PageObjects.observabilityLogExplorer.getPanelEntries(menu) + ); expect(await menuEntries[0].getVisibleText()).to.be('access'); expect(await menuEntries[1].getVisibleText()).to.be('error'); @@ -383,7 +396,9 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await retry.try(async () => { const panelTitleNode = await PageObjects.observabilityLogExplorer .getIntegrationsContextMenu() - .then((menu) => PageObjects.observabilityLogExplorer.getPanelTitle(menu)); + .then((menu: WebElementWrapper) => + PageObjects.observabilityLogExplorer.getPanelTitle(menu) + ); expect(await panelTitleNode.getVisibleText()).to.be('Apache HTTP Server'); }); @@ -391,7 +406,9 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await retry.try(async () => { const menuEntries = await PageObjects.observabilityLogExplorer .getIntegrationsContextMenu() - .then((menu) => PageObjects.observabilityLogExplorer.getPanelEntries(menu)); + .then((menu: WebElementWrapper) => + PageObjects.observabilityLogExplorer.getPanelEntries(menu) + ); expect(await menuEntries[0].getVisibleText()).to.be('access'); expect(await menuEntries[1].getVisibleText()).to.be('error'); @@ -402,7 +419,9 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await retry.try(async () => { const menuEntries = await PageObjects.observabilityLogExplorer .getIntegrationsContextMenu() - .then((menu) => PageObjects.observabilityLogExplorer.getPanelEntries(menu)); + .then((menu: WebElementWrapper) => + PageObjects.observabilityLogExplorer.getPanelEntries(menu) + ); expect(menuEntries.length).to.be(1); expect(await menuEntries[0].getVisibleText()).to.be('error'); @@ -418,7 +437,9 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await retry.try(async () => { const panelTitleNode = await PageObjects.observabilityLogExplorer .getIntegrationsContextMenu() - .then((menu) => PageObjects.observabilityLogExplorer.getPanelTitle(menu)); + .then((menu: WebElementWrapper) => + PageObjects.observabilityLogExplorer.getPanelTitle(menu) + ); expect(await panelTitleNode.getVisibleText()).to.be('Apache HTTP Server'); }); @@ -426,7 +447,9 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await retry.try(async () => { const menuEntries = await PageObjects.observabilityLogExplorer .getIntegrationsContextMenu() - .then((menu) => PageObjects.observabilityLogExplorer.getPanelEntries(menu)); + .then((menu: WebElementWrapper) => + PageObjects.observabilityLogExplorer.getPanelEntries(menu) + ); expect(await menuEntries[0].getVisibleText()).to.be('access'); menuEntries[0].click(); @@ -452,14 +475,14 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await PageObjects.observabilityLogExplorer.openDatasetSelector(); await PageObjects.observabilityLogExplorer .getUncategorizedTab() - .then((tab) => tab.click()); + .then((tab: WebElementWrapper) => tab.click()); }); it('should display a list of available datasets', async () => { await retry.try(async () => { const [panelTitleNode, menuEntries] = await PageObjects.observabilityLogExplorer .getUncategorizedContextMenu() - .then((menu) => + .then((menu: WebElementWrapper) => Promise.all([ PageObjects.observabilityLogExplorer.getPanelTitle(menu), PageObjects.observabilityLogExplorer.getPanelEntries(menu), @@ -477,7 +500,9 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await retry.try(async () => { const panelTitleNode = await PageObjects.observabilityLogExplorer .getUncategorizedContextMenu() - .then((menu) => PageObjects.observabilityLogExplorer.getPanelTitle(menu)); + .then((menu: WebElementWrapper) => + PageObjects.observabilityLogExplorer.getPanelTitle(menu) + ); expect(await panelTitleNode.getVisibleText()).to.be('Uncategorized'); }); @@ -487,7 +512,9 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await retry.try(async () => { const menuEntries = await PageObjects.observabilityLogExplorer .getUncategorizedContextMenu() - .then((menu) => PageObjects.observabilityLogExplorer.getPanelEntries(menu)); + .then((menu: WebElementWrapper) => + PageObjects.observabilityLogExplorer.getPanelEntries(menu) + ); expect(await menuEntries[0].getVisibleText()).to.be(expectedUncategorized[0]); expect(await menuEntries[1].getVisibleText()).to.be(expectedUncategorized[1]); @@ -499,7 +526,9 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await retry.try(async () => { const menuEntries = await PageObjects.observabilityLogExplorer .getUncategorizedContextMenu() - .then((menu) => PageObjects.observabilityLogExplorer.getPanelEntries(menu)); + .then((menu: WebElementWrapper) => + PageObjects.observabilityLogExplorer.getPanelEntries(menu) + ); expect(await menuEntries[0].getVisibleText()).to.be(expectedUncategorized[2]); expect(await menuEntries[1].getVisibleText()).to.be(expectedUncategorized[1]); @@ -511,7 +540,9 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await retry.try(async () => { const menuEntries = await PageObjects.observabilityLogExplorer .getUncategorizedContextMenu() - .then((menu) => PageObjects.observabilityLogExplorer.getPanelEntries(menu)); + .then((menu: WebElementWrapper) => + PageObjects.observabilityLogExplorer.getPanelEntries(menu) + ); expect(await menuEntries[0].getVisibleText()).to.be(expectedUncategorized[0]); expect(await menuEntries[1].getVisibleText()).to.be(expectedUncategorized[1]); @@ -523,7 +554,9 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await retry.try(async () => { const panelTitleNode = await PageObjects.observabilityLogExplorer .getUncategorizedContextMenu() - .then((menu) => PageObjects.observabilityLogExplorer.getPanelTitle(menu)); + .then((menu: WebElementWrapper) => + PageObjects.observabilityLogExplorer.getPanelTitle(menu) + ); expect(await panelTitleNode.getVisibleText()).to.be('Uncategorized'); }); @@ -531,7 +564,9 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await retry.try(async () => { const menuEntries = await PageObjects.observabilityLogExplorer .getUncategorizedContextMenu() - .then((menu) => PageObjects.observabilityLogExplorer.getPanelEntries(menu)); + .then((menu: WebElementWrapper) => + PageObjects.observabilityLogExplorer.getPanelEntries(menu) + ); expect(await menuEntries[0].getVisibleText()).to.be(expectedUncategorized[0]); expect(await menuEntries[1].getVisibleText()).to.be(expectedUncategorized[1]); @@ -543,7 +578,9 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await retry.try(async () => { const menuEntries = await PageObjects.observabilityLogExplorer .getUncategorizedContextMenu() - .then((menu) => PageObjects.observabilityLogExplorer.getPanelEntries(menu)); + .then((menu: WebElementWrapper) => + PageObjects.observabilityLogExplorer.getPanelEntries(menu) + ); expect(menuEntries.length).to.be(1); expect(await menuEntries[0].getVisibleText()).to.be('retail'); @@ -554,7 +591,9 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await retry.try(async () => { const panelTitleNode = await PageObjects.observabilityLogExplorer .getUncategorizedContextMenu() - .then((menu) => PageObjects.observabilityLogExplorer.getPanelTitle(menu)); + .then((menu: WebElementWrapper) => + PageObjects.observabilityLogExplorer.getPanelTitle(menu) + ); expect(await panelTitleNode.getVisibleText()).to.be('Uncategorized'); }); @@ -562,7 +601,9 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await retry.try(async () => { const menuEntries = await PageObjects.observabilityLogExplorer .getUncategorizedContextMenu() - .then((menu) => PageObjects.observabilityLogExplorer.getPanelEntries(menu)); + .then((menu: WebElementWrapper) => + PageObjects.observabilityLogExplorer.getPanelEntries(menu) + ); expect(await menuEntries[0].getVisibleText()).to.be(expectedUncategorized[0]); menuEntries[0].click(); @@ -585,14 +626,16 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { beforeEach(async () => { await browser.refresh(); await PageObjects.observabilityLogExplorer.openDatasetSelector(); - await PageObjects.observabilityLogExplorer.getDataViewsTab().then((tab) => tab.click()); + await PageObjects.observabilityLogExplorer + .getDataViewsTab() + .then((tab: WebElementWrapper) => tab.click()); }); it('should display a list of available data views', async () => { await retry.try(async () => { const [panelTitleNode, menuEntries] = await PageObjects.observabilityLogExplorer .getDataViewsContextMenu() - .then((menu) => + .then((menu: WebElementWrapper) => Promise.all([ PageObjects.observabilityLogExplorer.getPanelTitle(menu), PageObjects.observabilityLogExplorer.getPanelEntries(menu), @@ -614,7 +657,9 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await retry.try(async () => { const panelTitleNode = await PageObjects.observabilityLogExplorer .getDataViewsContextMenu() - .then((menu) => PageObjects.observabilityLogExplorer.getPanelTitle(menu)); + .then((menu: WebElementWrapper) => + PageObjects.observabilityLogExplorer.getPanelTitle(menu) + ); expect( await PageObjects.observabilityLogExplorer.getDataViewsContextMenuTitle( @@ -628,7 +673,9 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await retry.try(async () => { const menuEntries = await PageObjects.observabilityLogExplorer .getDataViewsContextMenu() - .then((menu) => PageObjects.observabilityLogExplorer.getPanelEntries(menu)); + .then((menu: WebElementWrapper) => + PageObjects.observabilityLogExplorer.getPanelEntries(menu) + ); expect(await menuEntries[0].getVisibleText()).to.be(sortedExpectedDataViews[2]); expect(await menuEntries[1].getVisibleText()).to.be(sortedExpectedDataViews[1]); @@ -640,7 +687,9 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await retry.try(async () => { const menuEntries = await PageObjects.observabilityLogExplorer .getDataViewsContextMenu() - .then((menu) => PageObjects.observabilityLogExplorer.getPanelEntries(menu)); + .then((menu: WebElementWrapper) => + PageObjects.observabilityLogExplorer.getPanelEntries(menu) + ); expect(await menuEntries[0].getVisibleText()).to.be(sortedExpectedDataViews[0]); expect(await menuEntries[1].getVisibleText()).to.be(sortedExpectedDataViews[1]); @@ -652,7 +701,9 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await retry.try(async () => { const panelTitleNode = await PageObjects.observabilityLogExplorer .getDataViewsContextMenu() - .then((menu) => PageObjects.observabilityLogExplorer.getPanelTitle(menu)); + .then((menu: WebElementWrapper) => + PageObjects.observabilityLogExplorer.getPanelTitle(menu) + ); expect( await PageObjects.observabilityLogExplorer.getDataViewsContextMenuTitle( @@ -664,7 +715,9 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await retry.try(async () => { const menuEntries = await PageObjects.observabilityLogExplorer .getDataViewsContextMenu() - .then((menu) => PageObjects.observabilityLogExplorer.getPanelEntries(menu)); + .then((menu: WebElementWrapper) => + PageObjects.observabilityLogExplorer.getPanelEntries(menu) + ); expect(await menuEntries[0].getVisibleText()).to.be(expectedDataViews[0]); expect(await menuEntries[1].getVisibleText()).to.be(expectedDataViews[1]); @@ -676,7 +729,9 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await retry.try(async () => { const menuEntries = await PageObjects.observabilityLogExplorer .getDataViewsContextMenu() - .then((menu) => PageObjects.observabilityLogExplorer.getPanelEntries(menu)); + .then((menu: WebElementWrapper) => + PageObjects.observabilityLogExplorer.getPanelEntries(menu) + ); expect(menuEntries.length).to.be(2); expect(await menuEntries[0].getVisibleText()).to.be('logs-*'); @@ -688,7 +743,9 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await retry.try(async () => { const panelTitleNode = await PageObjects.observabilityLogExplorer .getDataViewsContextMenu() - .then((menu) => PageObjects.observabilityLogExplorer.getPanelTitle(menu)); + .then((menu: WebElementWrapper) => + PageObjects.observabilityLogExplorer.getPanelTitle(menu) + ); expect( await PageObjects.observabilityLogExplorer.getDataViewsContextMenuTitle( @@ -700,7 +757,9 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await retry.try(async () => { const menuEntries = await PageObjects.observabilityLogExplorer .getDataViewsContextMenu() - .then((menu) => PageObjects.observabilityLogExplorer.getPanelEntries(menu)); + .then((menu: WebElementWrapper) => + PageObjects.observabilityLogExplorer.getPanelEntries(menu) + ); expect(await menuEntries[2].getVisibleText()).to.be(expectedDataViews[2]); menuEntries[2].click(); @@ -733,7 +792,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await retry.try(async () => { const [panelTitleNode, menuEntries] = await PageObjects.observabilityLogExplorer .getIntegrationsContextMenu() - .then((menu) => + .then((menu: WebElementWrapper) => Promise.all([ PageObjects.observabilityLogExplorer.getPanelTitle(menu), PageObjects.observabilityLogExplorer.getPanelEntries(menu), @@ -751,7 +810,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await retry.try(async () => { const [panelTitleNode, menuEntries] = await PageObjects.observabilityLogExplorer .getIntegrationsContextMenu() - .then((menu) => + .then((menu: WebElementWrapper) => Promise.all([ PageObjects.observabilityLogExplorer.getPanelTitle(menu), PageObjects.observabilityLogExplorer.getPanelEntries(menu), @@ -803,7 +862,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await retry.try(async () => { const [panelTitleNode, menuEntries] = await PageObjects.observabilityLogExplorer .getIntegrationsContextMenu() - .then((menu) => + .then((menu: WebElementWrapper) => Promise.all([ PageObjects.observabilityLogExplorer.getPanelTitle(menu), PageObjects.observabilityLogExplorer.getPanelEntries(menu), @@ -820,7 +879,9 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await retry.try(async () => { const menuEntries = await PageObjects.observabilityLogExplorer .getIntegrationsContextMenu() - .then((menu) => PageObjects.observabilityLogExplorer.getPanelEntries(menu)); + .then((menu: WebElementWrapper) => + PageObjects.observabilityLogExplorer.getPanelEntries(menu) + ); expect(menuEntries.length).to.be(1); expect(await menuEntries[0].getVisibleText()).to.be('error'); @@ -829,7 +890,9 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { // Navigate back to integrations const panelTitleNode = await PageObjects.observabilityLogExplorer .getIntegrationsContextMenu() - .then((menu) => PageObjects.observabilityLogExplorer.getPanelTitle(menu)); + .then((menu: WebElementWrapper) => + PageObjects.observabilityLogExplorer.getPanelTitle(menu) + ); panelTitleNode.click(); await retry.try(async () => { @@ -846,7 +909,9 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await retry.try(async () => { const menuEntries = await PageObjects.observabilityLogExplorer .getIntegrationsContextMenu() - .then((menu) => PageObjects.observabilityLogExplorer.getPanelEntries(menu)); + .then((menu: WebElementWrapper) => + PageObjects.observabilityLogExplorer.getPanelEntries(menu) + ); const searchValue = await PageObjects.observabilityLogExplorer.getSearchFieldValue(); expect(searchValue).to.eql('err'); diff --git a/x-pack/test/functional/apps/observability_log_explorer/filter_controls.ts b/x-pack/test/functional/apps/observability_log_explorer/filter_controls.ts index db04f6251d9bc..36087a23e8c4c 100644 --- a/x-pack/test/functional/apps/observability_log_explorer/filter_controls.ts +++ b/x-pack/test/functional/apps/observability_log_explorer/filter_controls.ts @@ -4,7 +4,7 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import { FtrProviderContext } from '../../ftr_provider_context'; +import { FtrProviderContext } from './config'; export default function ({ getService, getPageObjects }: FtrProviderContext) { const kibanaServer = getService('kibanaServer'); diff --git a/x-pack/test/functional/apps/observability_log_explorer/header_menu.ts b/x-pack/test/functional/apps/observability_log_explorer/header_menu.ts index eb3c94b62403b..f87edc5fc23a5 100644 --- a/x-pack/test/functional/apps/observability_log_explorer/header_menu.ts +++ b/x-pack/test/functional/apps/observability_log_explorer/header_menu.ts @@ -5,7 +5,7 @@ * 2.0. */ import expect from '@kbn/expect'; -import { FtrProviderContext } from '../../ftr_provider_context'; +import { FtrProviderContext } from './config'; export default function ({ getService, getPageObjects }: FtrProviderContext) { const browser = getService('browser'); diff --git a/x-pack/test/functional/apps/observability_log_explorer/index.ts b/x-pack/test/functional/apps/observability_log_explorer/index.ts index 7a767baa887de..c1114211b41a9 100644 --- a/x-pack/test/functional/apps/observability_log_explorer/index.ts +++ b/x-pack/test/functional/apps/observability_log_explorer/index.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { FtrProviderContext } from '../../ftr_provider_context'; +import { FtrProviderContext } from './config'; export default function ({ loadTestFile }: FtrProviderContext) { describe('Observability Log Explorer', function () { diff --git a/x-pack/test/functional/apps/snapshot_restore/snapshot_restore.ts b/x-pack/test/functional/apps/snapshot_restore/snapshot_restore.ts index a1a6bfe6276f5..279babade39ff 100644 --- a/x-pack/test/functional/apps/snapshot_restore/snapshot_restore.ts +++ b/x-pack/test/functional/apps/snapshot_restore/snapshot_restore.ts @@ -38,7 +38,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { }); // Wait for snapshot to be ready - await pageObjects.common.sleep(1000); + await pageObjects.common.sleep(2000); // Refresh page so that the snapshot shows up in the snapshots table await browser.refresh(); diff --git a/x-pack/test/functional/es_archives/rule_keyword_family/const_keyword/mappings.json b/x-pack/test/functional/es_archives/rule_keyword_family/const_keyword/mappings.json index 7e3d74f840142..8622a0f62cd5a 100644 --- a/x-pack/test/functional/es_archives/rule_keyword_family/const_keyword/mappings.json +++ b/x-pack/test/functional/es_archives/rule_keyword_family/const_keyword/mappings.json @@ -39,7 +39,6 @@ }, "settings": { "index": { - "refresh_interval": "1s", "number_of_replicas": "1", "number_of_shards": "1" } diff --git a/x-pack/test/functional/es_archives/rule_keyword_family/keyword/mappings.json b/x-pack/test/functional/es_archives/rule_keyword_family/keyword/mappings.json index 9d5274a002279..233b1148f04b4 100644 --- a/x-pack/test/functional/es_archives/rule_keyword_family/keyword/mappings.json +++ b/x-pack/test/functional/es_archives/rule_keyword_family/keyword/mappings.json @@ -25,7 +25,6 @@ }, "settings": { "index": { - "refresh_interval": "1s", "number_of_replicas": "1", "number_of_shards": "1" } diff --git a/x-pack/test/functional/es_archives/security_solution/alerts/8.8.0/data.json b/x-pack/test/functional/es_archives/security_solution/alerts/8.8.0/data.json new file mode 100644 index 0000000000000..dc677dd5bf812 --- /dev/null +++ b/x-pack/test/functional/es_archives/security_solution/alerts/8.8.0/data.json @@ -0,0 +1,422 @@ +{ + "type": "doc", + "value": { + "id": "eabbdefc23da981f2b74ab58b82622a97bb9878caa11bc914e2adfacc94780f1", + "index": ".alerts-security.alerts-default", + "source": { + "@timestamp": "2023-04-27T11:03:57.906Z", + "Endpoint": { + "capabilities": [ + "isolation", + "kill_process", + "suspend_process", + "running_processes", + "get_file", + "execute" + ], + "configuration": { + "isolation": true + }, + "policy": { + "applied": { + "endpoint_policy_version": 3, + "id": "C2A9093E-E289-4C0A-AA44-8C32A414FA7A", + "name": "With Eventing", + "status": "success", + "version": 5 + } + }, + "state": { + "isolation": true + }, + "status": "enrolled" + }, + "agent": { + "id": "b563ce99-e373-4a1f-a5fe-97e956140aeb", + "type": "endpoint", + "version": "8.8.0" + }, + "data_stream": { + "dataset": "endpoint.alerts", + "namespace": "default", + "type": "logs" + }, + "dll": [ + { + "Ext": { + "compile_time": 1534424710, + "malware_classification": { + "identifier": "Whitelisted", + "score": 0, + "threshold": 0, + "version": "3.0.0" + }, + "mapped_address": 5362483200, + "mapped_size": 0 + }, + "code_signature": { + "subject_name": "Cybereason Inc", + "trusted": true + }, + "hash": { + "md5": "1f2d082566b0fc5f2c238a5180db7451", + "sha1": "ca85243c0af6a6471bdaa560685c51eefd6dbc0d", + "sha256": "8ad40c90a611d36eb8f9eb24fa04f7dbca713db383ff55a03aa0f382e92061a2" + }, + "path": "C:\\Program Files\\Cybereason ActiveProbe\\AmSvc.exe", + "pe": { + "architecture": "x64" + } + } + ], + "ecs": { + "version": "1.4.0" + }, + "elastic": { + "agent": { + "id": "b563ce99-e373-4a1f-a5fe-97e956140aeb" + } + }, + "event.action": "creation", + "event.agent_id_status": "auth_metadata_missing", + "event.category": "malware", + "event.code": "malicious_file", + "event.dataset": "endpoint", + "event.id": "b28993d4-8b8a-4f0f-9f54-84a89bad66ae", + "event.ingested": "2023-04-27T10:58:03Z", + "event.kind": "signal", + "event.module": "endpoint", + "event.sequence": 5826, + "event.type": "creation", + "file": { + "Ext": { + "code_signature": [ + { + "subject_name": "bad signer", + "trusted": false + } + ], + "malware_classification": { + "identifier": "endpointpe", + "score": 1, + "threshold": 0.66, + "version": "3.0.33" + }, + "quarantine_message": "fake quarantine message", + "quarantine_result": true, + "temp_file_path": "C:/temp/fake_malware.exe" + }, + "accessed": 1682752652103, + "created": 1682752652103, + "hash": { + "md5": "fake file md5", + "sha1": "fake file sha1", + "sha256": "fake file sha256" + }, + "mtime": 1682752652103, + "name": "fake_malware.exe", + "owner": "SYSTEM", + "path": "C:/fake_malware.exe", + "size": 3456 + }, + "user": { + "name": "user1" + }, + "host": { + "architecture": "wtnozeqvub", + "hostname": "Host-fwarau82er", + "id": "4260adf9-5e63-445d-92c6-e03359bcd342", + "ip": [ + "10.249.37.72", + "10.150.39.243", + "10.186.17.170" + ], + "mac": [ + "f5-f-97-dc-20-67", + "b5-56-ca-98-81-ca", + "22-86-39-4c-87-33" + ], + "name": "Host-fwarau82er", + "os": { + "Ext": { + "variant": "Darwin" + }, + "family": "Darwin", + "full": "macOS Monterey", + "name": "macOS", + "platform": "macOS", + "version": "12.6.1" + } + }, + "kibana.alert.ancestors": [ + { + "depth": 0, + "id": "vT9cwocBh3b8EMpD8lsi", + "index": ".ds-logs-endpoint.alerts-default-2023.04.27-000001", + "type": "event" + } + ], + "kibana.alert.depth": 1, + "kibana.alert.last_detected": "2023-04-27T11:03:57.993Z", + "kibana.alert.original_event.action": "creation", + "kibana.alert.original_event.agent_id_status": "auth_metadata_missing", + "kibana.alert.original_event.category": "malware", + "kibana.alert.original_event.code": "malicious_file", + "kibana.alert.original_event.dataset": "endpoint", + "kibana.alert.original_event.id": "b28993d4-8b8a-4f0f-9f54-84a89bad66ae", + "kibana.alert.original_event.ingested": "2023-04-27T10:58:03Z", + "kibana.alert.original_event.kind": "alert", + "kibana.alert.original_event.module": "endpoint", + "kibana.alert.original_event.sequence": 5826, + "kibana.alert.original_event.type": "creation", + "kibana.alert.original_time": "2023-04-29T07:17:32.103Z", + "kibana.alert.reason": "malware event with process malware writer, file fake_malware.exe, on Host-fwarau82er created medium alert Endpoint Security.", + "kibana.alert.risk_score": 47, + "kibana.alert.rule.actions": [ + ], + "kibana.alert.rule.author": [ + "Elastic" + ], + "kibana.alert.rule.category": "Custom Query Rule", + "kibana.alert.rule.consumer": "siem", + "kibana.alert.rule.created_at": "2023-04-27T10:58:27.546Z", + "kibana.alert.rule.created_by": "elastic", + "kibana.alert.rule.description": "Generates a detection alert each time an Elastic Endpoint Security alert is received. Enabling this rule allows you to immediately begin investigating your Endpoint alerts.", + "kibana.alert.rule.enabled": true, + "kibana.alert.rule.exceptions_list": [ + { + "id": "endpoint_list", + "list_id": "endpoint_list", + "namespace_type": "agnostic", + "type": "endpoint" + } + ], + "kibana.alert.rule.execution.uuid": "ebf843ff-e0e1-47f8-9ed2-cc8066afbcef", + "kibana.alert.rule.false_positives": [ + ], + "kibana.alert.rule.from": "now-10m", + "kibana.alert.rule.immutable": true, + "kibana.alert.rule.indices": [ + "logs-endpoint.alerts-*" + ], + "kibana.alert.rule.interval": "5m", + "kibana.alert.rule.license": "Elastic License v2", + "kibana.alert.rule.max_signals": 10000, + "kibana.alert.rule.name": "Endpoint Security", + "kibana.alert.rule.parameters": { + "author": [ + "Elastic" + ], + "description": "Generates a detection alert each time an Elastic Endpoint Security alert is received. Enabling this rule allows you to immediately begin investigating your Endpoint alerts.", + "exceptions_list": [ + { + "id": "endpoint_list", + "list_id": "endpoint_list", + "namespace_type": "agnostic", + "type": "endpoint" + } + ], + "false_positives": [ + ], + "from": "now-10m", + "immutable": true, + "index": [ + "logs-endpoint.alerts-*" + ], + "language": "kuery", + "license": "Elastic License v2", + "max_signals": 10000, + "query": "event.kind:alert and event.module:(endpoint and not endgame)\n", + "references": [ + ], + "related_integrations": [ + { + "package": "endpoint", + "version": "^8.2.0" + } + ], + "required_fields": [ + { + "ecs": true, + "name": "event.kind", + "type": "keyword" + }, + { + "ecs": true, + "name": "event.module", + "type": "keyword" + } + ], + "risk_score": 47, + "risk_score_mapping": [ + { + "field": "event.risk_score", + "operator": "equals", + "value": "" + } + ], + "rule_id": "9a1a2dae-0b5f-4c3d-8305-a268d404c306", + "rule_name_override": "message", + "setup": "", + "severity": "medium", + "severity_mapping": [ + { + "field": "event.severity", + "operator": "equals", + "severity": "low", + "value": "21" + }, + { + "field": "event.severity", + "operator": "equals", + "severity": "medium", + "value": "47" + }, + { + "field": "event.severity", + "operator": "equals", + "severity": "high", + "value": "73" + }, + { + "field": "event.severity", + "operator": "equals", + "severity": "critical", + "value": "99" + } + ], + "threat": [ + ], + "timestamp_override": "event.ingested", + "to": "now", + "type": "query", + "version": 101 + }, + "kibana.alert.rule.producer": "siem", + "kibana.alert.rule.references": [ + ], + "kibana.alert.rule.revision": 0, + "kibana.alert.rule.risk_score": 47, + "kibana.alert.rule.risk_score_mapping": [ + { + "field": "event.risk_score", + "operator": "equals", + "value": "" + } + ], + "kibana.alert.rule.rule_id": "9a1a2dae-0b5f-4c3d-8305-a268d404c306", + "kibana.alert.rule.rule_name_override": "message", + "kibana.alert.rule.rule_type_id": "siem.queryRule", + "kibana.alert.rule.severity": "medium", + "kibana.alert.rule.severity_mapping": [ + { + "field": "event.severity", + "operator": "equals", + "severity": "low", + "value": "21" + }, + { + "field": "event.severity", + "operator": "equals", + "severity": "medium", + "value": "47" + }, + { + "field": "event.severity", + "operator": "equals", + "severity": "high", + "value": "73" + }, + { + "field": "event.severity", + "operator": "equals", + "severity": "critical", + "value": "99" + } + ], + "kibana.alert.rule.tags": [ + "Elastic", + "Endpoint Security" + ], + "kibana.alert.rule.threat": [ + ], + "kibana.alert.rule.timestamp_override": "event.ingested", + "kibana.alert.rule.to": "now", + "kibana.alert.rule.type": "query", + "kibana.alert.rule.updated_at": "2023-04-27T10:58:27.546Z", + "kibana.alert.rule.updated_by": "elastic", + "kibana.alert.rule.uuid": "7015a3e2-e4ea-11ed-8c11-49608884878f", + "kibana.alert.rule.version": 101, + "kibana.alert.severity": "medium", + "kibana.alert.start": "2023-04-27T11:03:57.993Z", + "kibana.alert.status": "active", + "kibana.alert.url": "http://localhost:5601/app/security/alerts/redirect/eabbdefc23da981f2b74ab58b82622a97bb9878caa11bc914e2adfacc94780f1?index=.alerts-security.alerts-default×tamp=2023-04-27T11:03:57.906Z", + "kibana.alert.uuid": "eabbdefc23da981f2b74ab58b82622a97bb9878caa11bc914e2adfacc94780f1", + "kibana.alert.workflow_status": "open", + "kibana.space_ids": [ + "default" + ], + "kibana.version": "8.8.0", + "process": { + "Ext": { + "ancestry": [ + "qa5jgw1wr7", + "5k1hclygc6" + ], + "code_signature": [ + { + "subject_name": "bad signer", + "trusted": false + } + ], + "token": { + "domain": "NT AUTHORITY", + "integrity_level": 16384, + "integrity_level_name": "system", + "privileges": [ + { + "description": "Replace a process level token", + "enabled": false, + "name": "SeAssignPrimaryTokenPrivilege" + } + ], + "sid": "S-1-5-18", + "type": "tokenPrimary", + "user": "SYSTEM" + }, + "user": "SYSTEM" + }, + "entity_id": "nqh8ts6ves", + "entry_leader": { + "entity_id": "jnm38bel0w", + "name": "fake entry", + "pid": 791 + }, + "executable": "C:/malware.exe", + "group_leader": { + "entity_id": "jnm38bel0w", + "name": "fake leader", + "pid": 848 + }, + "hash": { + "md5": "fake md5", + "sha1": "fake sha1", + "sha256": "fake sha256" + }, + "name": "malware writer", + "parent": { + "entity_id": "qa5jgw1wr7", + "pid": 1 + }, + "pid": 2, + "session_leader": { + "entity_id": "jnm38bel0w", + "name": "fake session", + "pid": 909 + }, + "start": 1682752652103, + "uptime": 0 + } + } + } +} diff --git a/x-pack/test/functional/es_archives/security_solution/alerts/8.8.0/mappings.json b/x-pack/test/functional/es_archives/security_solution/alerts/8.8.0/mappings.json new file mode 100644 index 0000000000000..f5a6e53cc4d60 --- /dev/null +++ b/x-pack/test/functional/es_archives/security_solution/alerts/8.8.0/mappings.json @@ -0,0 +1,7900 @@ +{ + "type": "index", + "value": { + "aliases": { + ".alerts-security.alerts-default": { + "is_write_index": true + }, + ".siem-signals-default": { + "is_write_index": false + } + }, + "index": ".internal.alerts-security.alerts-default-000001", + "mappings": { + "_meta": { + "kibana": { + "version": "8.8.0" + }, + "managed": true, + "namespace": "default" + }, + "dynamic": "false", + "properties": { + "@timestamp": { + "type": "date" + }, + "agent": { + "properties": { + "build": { + "properties": { + "original": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "ephemeral_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "client": { + "properties": { + "address": { + "ignore_above": 1024, + "type": "keyword" + }, + "as": { + "properties": { + "number": { + "type": "long" + }, + "organization": { + "properties": { + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "bytes": { + "type": "long" + }, + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "geo": { + "properties": { + "city_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "continent_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "continent_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "country_iso_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "country_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "location": { + "type": "geo_point" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "postal_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "region_iso_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "region_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "timezone": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "ip": { + "type": "ip" + }, + "mac": { + "ignore_above": 1024, + "type": "keyword" + }, + "nat": { + "properties": { + "ip": { + "type": "ip" + }, + "port": { + "type": "long" + } + } + }, + "packets": { + "type": "long" + }, + "port": { + "type": "long" + }, + "registered_domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "subdomain": { + "ignore_above": 1024, + "type": "keyword" + }, + "top_level_domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "user": { + "properties": { + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "email": { + "ignore_above": 1024, + "type": "keyword" + }, + "full_name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "group": { + "properties": { + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "roles": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "cloud": { + "properties": { + "account": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "availability_zone": { + "ignore_above": 1024, + "type": "keyword" + }, + "instance": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "machine": { + "properties": { + "type": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "origin": { + "properties": { + "account": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "availability_zone": { + "ignore_above": 1024, + "type": "keyword" + }, + "instance": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "machine": { + "properties": { + "type": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "project": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "provider": { + "ignore_above": 1024, + "type": "keyword" + }, + "region": { + "ignore_above": 1024, + "type": "keyword" + }, + "service": { + "properties": { + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "project": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "provider": { + "ignore_above": 1024, + "type": "keyword" + }, + "region": { + "ignore_above": 1024, + "type": "keyword" + }, + "service": { + "properties": { + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "target": { + "properties": { + "account": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "availability_zone": { + "ignore_above": 1024, + "type": "keyword" + }, + "instance": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "machine": { + "properties": { + "type": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "project": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "provider": { + "ignore_above": 1024, + "type": "keyword" + }, + "region": { + "ignore_above": 1024, + "type": "keyword" + }, + "service": { + "properties": { + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + } + } + }, + "container": { + "properties": { + "cpu": { + "properties": { + "usage": { + "scaling_factor": 1000, + "type": "scaled_float" + } + } + }, + "disk": { + "properties": { + "read": { + "properties": { + "bytes": { + "type": "long" + } + } + }, + "write": { + "properties": { + "bytes": { + "type": "long" + } + } + } + } + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "image": { + "properties": { + "hash": { + "properties": { + "all": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "tag": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "labels": { + "type": "object" + }, + "memory": { + "properties": { + "usage": { + "scaling_factor": 1000, + "type": "scaled_float" + } + } + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "network": { + "properties": { + "egress": { + "properties": { + "bytes": { + "type": "long" + } + } + }, + "ingress": { + "properties": { + "bytes": { + "type": "long" + } + } + } + } + }, + "runtime": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "destination": { + "properties": { + "address": { + "ignore_above": 1024, + "type": "keyword" + }, + "as": { + "properties": { + "number": { + "type": "long" + }, + "organization": { + "properties": { + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "bytes": { + "type": "long" + }, + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "geo": { + "properties": { + "city_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "continent_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "continent_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "country_iso_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "country_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "location": { + "type": "geo_point" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "postal_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "region_iso_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "region_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "timezone": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "ip": { + "type": "ip" + }, + "mac": { + "ignore_above": 1024, + "type": "keyword" + }, + "nat": { + "properties": { + "ip": { + "type": "ip" + }, + "port": { + "type": "long" + } + } + }, + "packets": { + "type": "long" + }, + "port": { + "type": "long" + }, + "registered_domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "subdomain": { + "ignore_above": 1024, + "type": "keyword" + }, + "top_level_domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "user": { + "properties": { + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "email": { + "ignore_above": 1024, + "type": "keyword" + }, + "full_name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "group": { + "properties": { + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "roles": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "device": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "manufacturer": { + "ignore_above": 1024, + "type": "keyword" + }, + "model": { + "properties": { + "identifier": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "dll": { + "properties": { + "code_signature": { + "properties": { + "digest_algorithm": { + "ignore_above": 1024, + "type": "keyword" + }, + "exists": { + "type": "boolean" + }, + "signing_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "status": { + "ignore_above": 1024, + "type": "keyword" + }, + "subject_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "team_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "timestamp": { + "type": "date" + }, + "trusted": { + "type": "boolean" + }, + "valid": { + "type": "boolean" + } + } + }, + "hash": { + "properties": { + "md5": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha1": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha256": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha384": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha512": { + "ignore_above": 1024, + "type": "keyword" + }, + "ssdeep": { + "ignore_above": 1024, + "type": "keyword" + }, + "tlsh": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "path": { + "ignore_above": 1024, + "type": "keyword" + }, + "pe": { + "properties": { + "architecture": { + "ignore_above": 1024, + "type": "keyword" + }, + "company": { + "ignore_above": 1024, + "type": "keyword" + }, + "description": { + "ignore_above": 1024, + "type": "keyword" + }, + "file_version": { + "ignore_above": 1024, + "type": "keyword" + }, + "imphash": { + "ignore_above": 1024, + "type": "keyword" + }, + "original_file_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "pehash": { + "ignore_above": 1024, + "type": "keyword" + }, + "product": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "dns": { + "properties": { + "answers": { + "properties": { + "class": { + "ignore_above": 1024, + "type": "keyword" + }, + "data": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "ttl": { + "type": "long" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "header_flags": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "op_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "question": { + "properties": { + "class": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "registered_domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "subdomain": { + "ignore_above": 1024, + "type": "keyword" + }, + "top_level_domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "resolved_ip": { + "type": "ip" + }, + "response_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "ecs": { + "properties": { + "version": { + "type": "keyword" + } + } + }, + "email": { + "properties": { + "attachments": { + "properties": { + "file": { + "properties": { + "extension": { + "ignore_above": 1024, + "type": "keyword" + }, + "hash": { + "properties": { + "md5": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha1": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha256": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha384": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha512": { + "ignore_above": 1024, + "type": "keyword" + }, + "ssdeep": { + "ignore_above": 1024, + "type": "keyword" + }, + "tlsh": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "mime_type": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "size": { + "type": "long" + } + } + } + }, + "type": "nested" + }, + "bcc": { + "properties": { + "address": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "cc": { + "properties": { + "address": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "content_type": { + "ignore_above": 1024, + "type": "keyword" + }, + "delivery_timestamp": { + "type": "date" + }, + "direction": { + "ignore_above": 1024, + "type": "keyword" + }, + "from": { + "properties": { + "address": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "local_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "message_id": { + "type": "wildcard" + }, + "origination_timestamp": { + "type": "date" + }, + "reply_to": { + "properties": { + "address": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "sender": { + "properties": { + "address": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "subject": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "to": { + "properties": { + "address": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "x_mailer": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "error": { + "properties": { + "code": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "message": { + "type": "match_only_text" + }, + "stack_trace": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "type": "wildcard" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "event": { + "properties": { + "action": { + "type": "keyword" + }, + "agent_id_status": { + "ignore_above": 1024, + "type": "keyword" + }, + "category": { + "ignore_above": 1024, + "type": "keyword" + }, + "code": { + "ignore_above": 1024, + "type": "keyword" + }, + "created": { + "type": "date" + }, + "dataset": { + "ignore_above": 1024, + "type": "keyword" + }, + "duration": { + "type": "long" + }, + "end": { + "type": "date" + }, + "hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "ingested": { + "type": "date" + }, + "kind": { + "type": "keyword" + }, + "module": { + "ignore_above": 1024, + "type": "keyword" + }, + "original": { + "type": "keyword" + }, + "outcome": { + "ignore_above": 1024, + "type": "keyword" + }, + "provider": { + "ignore_above": 1024, + "type": "keyword" + }, + "reason": { + "ignore_above": 1024, + "type": "keyword" + }, + "reference": { + "ignore_above": 1024, + "type": "keyword" + }, + "risk_score": { + "type": "float" + }, + "risk_score_norm": { + "type": "float" + }, + "sequence": { + "type": "long" + }, + "severity": { + "type": "long" + }, + "start": { + "type": "date" + }, + "timezone": { + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "url": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "faas": { + "properties": { + "coldstart": { + "type": "boolean" + }, + "execution": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "trigger": { + "properties": { + "request_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + } + }, + "type": "nested" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "file": { + "properties": { + "accessed": { + "type": "date" + }, + "attributes": { + "ignore_above": 1024, + "type": "keyword" + }, + "code_signature": { + "properties": { + "digest_algorithm": { + "ignore_above": 1024, + "type": "keyword" + }, + "exists": { + "type": "boolean" + }, + "signing_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "status": { + "ignore_above": 1024, + "type": "keyword" + }, + "subject_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "team_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "timestamp": { + "type": "date" + }, + "trusted": { + "type": "boolean" + }, + "valid": { + "type": "boolean" + } + } + }, + "created": { + "type": "date" + }, + "ctime": { + "type": "date" + }, + "device": { + "ignore_above": 1024, + "type": "keyword" + }, + "directory": { + "ignore_above": 1024, + "type": "keyword" + }, + "drive_letter": { + "ignore_above": 1, + "type": "keyword" + }, + "elf": { + "properties": { + "architecture": { + "ignore_above": 1024, + "type": "keyword" + }, + "byte_order": { + "ignore_above": 1024, + "type": "keyword" + }, + "cpu_type": { + "ignore_above": 1024, + "type": "keyword" + }, + "creation_date": { + "type": "date" + }, + "exports": { + "type": "flattened" + }, + "header": { + "properties": { + "abi_version": { + "ignore_above": 1024, + "type": "keyword" + }, + "class": { + "ignore_above": 1024, + "type": "keyword" + }, + "data": { + "ignore_above": 1024, + "type": "keyword" + }, + "entrypoint": { + "type": "long" + }, + "object_version": { + "ignore_above": 1024, + "type": "keyword" + }, + "os_abi": { + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "imports": { + "type": "flattened" + }, + "sections": { + "properties": { + "chi2": { + "type": "long" + }, + "entropy": { + "type": "long" + }, + "flags": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "physical_offset": { + "ignore_above": 1024, + "type": "keyword" + }, + "physical_size": { + "type": "long" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "virtual_address": { + "type": "long" + }, + "virtual_size": { + "type": "long" + } + }, + "type": "nested" + }, + "segments": { + "properties": { + "sections": { + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + } + }, + "type": "nested" + }, + "shared_libraries": { + "ignore_above": 1024, + "type": "keyword" + }, + "telfhash": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "extension": { + "ignore_above": 1024, + "type": "keyword" + }, + "fork_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "gid": { + "ignore_above": 1024, + "type": "keyword" + }, + "group": { + "ignore_above": 1024, + "type": "keyword" + }, + "hash": { + "properties": { + "md5": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha1": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha256": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha384": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha512": { + "ignore_above": 1024, + "type": "keyword" + }, + "ssdeep": { + "ignore_above": 1024, + "type": "keyword" + }, + "tlsh": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "inode": { + "ignore_above": 1024, + "type": "keyword" + }, + "mime_type": { + "ignore_above": 1024, + "type": "keyword" + }, + "mode": { + "ignore_above": 1024, + "type": "keyword" + }, + "mtime": { + "type": "date" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "owner": { + "ignore_above": 1024, + "type": "keyword" + }, + "path": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "pe": { + "properties": { + "architecture": { + "ignore_above": 1024, + "type": "keyword" + }, + "company": { + "ignore_above": 1024, + "type": "keyword" + }, + "description": { + "ignore_above": 1024, + "type": "keyword" + }, + "file_version": { + "ignore_above": 1024, + "type": "keyword" + }, + "imphash": { + "ignore_above": 1024, + "type": "keyword" + }, + "original_file_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "pehash": { + "ignore_above": 1024, + "type": "keyword" + }, + "product": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "size": { + "type": "long" + }, + "target_path": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "uid": { + "ignore_above": 1024, + "type": "keyword" + }, + "x509": { + "properties": { + "alternative_names": { + "ignore_above": 1024, + "type": "keyword" + }, + "issuer": { + "properties": { + "common_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "country": { + "ignore_above": 1024, + "type": "keyword" + }, + "distinguished_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "locality": { + "ignore_above": 1024, + "type": "keyword" + }, + "organization": { + "ignore_above": 1024, + "type": "keyword" + }, + "organizational_unit": { + "ignore_above": 1024, + "type": "keyword" + }, + "state_or_province": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "not_after": { + "type": "date" + }, + "not_before": { + "type": "date" + }, + "public_key_algorithm": { + "ignore_above": 1024, + "type": "keyword" + }, + "public_key_curve": { + "ignore_above": 1024, + "type": "keyword" + }, + "public_key_exponent": { + "type": "long" + }, + "public_key_size": { + "type": "long" + }, + "serial_number": { + "ignore_above": 1024, + "type": "keyword" + }, + "signature_algorithm": { + "ignore_above": 1024, + "type": "keyword" + }, + "subject": { + "properties": { + "common_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "country": { + "ignore_above": 1024, + "type": "keyword" + }, + "distinguished_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "locality": { + "ignore_above": 1024, + "type": "keyword" + }, + "organization": { + "ignore_above": 1024, + "type": "keyword" + }, + "organizational_unit": { + "ignore_above": 1024, + "type": "keyword" + }, + "state_or_province": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "version_number": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "group": { + "properties": { + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "host": { + "properties": { + "architecture": { + "ignore_above": 1024, + "type": "keyword" + }, + "boot": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "cpu": { + "properties": { + "usage": { + "scaling_factor": 1000, + "type": "scaled_float" + } + } + }, + "disk": { + "properties": { + "read": { + "properties": { + "bytes": { + "type": "long" + } + } + }, + "write": { + "properties": { + "bytes": { + "type": "long" + } + } + } + } + }, + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "geo": { + "properties": { + "city_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "continent_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "continent_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "country_iso_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "country_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "location": { + "type": "geo_point" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "postal_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "region_iso_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "region_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "timezone": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "hostname": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "ip": { + "type": "ip" + }, + "mac": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "network": { + "properties": { + "egress": { + "properties": { + "bytes": { + "type": "long" + }, + "packets": { + "type": "long" + } + } + }, + "ingress": { + "properties": { + "bytes": { + "type": "long" + }, + "packets": { + "type": "long" + } + } + } + } + }, + "os": { + "properties": { + "family": { + "ignore_above": 1024, + "type": "keyword" + }, + "full": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "kernel": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "platform": { + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "pid_ns_ino": { + "ignore_above": 1024, + "type": "keyword" + }, + "risk": { + "properties": { + "calculated_level": { + "ignore_above": 1024, + "type": "keyword" + }, + "calculated_score": { + "type": "float" + }, + "calculated_score_norm": { + "type": "float" + }, + "static_level": { + "ignore_above": 1024, + "type": "keyword" + }, + "static_score": { + "type": "float" + }, + "static_score_norm": { + "type": "float" + } + } + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "uptime": { + "type": "long" + } + } + }, + "http": { + "properties": { + "request": { + "properties": { + "body": { + "properties": { + "bytes": { + "type": "long" + }, + "content": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "type": "wildcard" + } + } + }, + "bytes": { + "type": "long" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "method": { + "ignore_above": 1024, + "type": "keyword" + }, + "mime_type": { + "ignore_above": 1024, + "type": "keyword" + }, + "referrer": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "response": { + "properties": { + "body": { + "properties": { + "bytes": { + "type": "long" + }, + "content": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "type": "wildcard" + } + } + }, + "bytes": { + "type": "long" + }, + "mime_type": { + "ignore_above": 1024, + "type": "keyword" + }, + "status_code": { + "type": "long" + } + } + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "kibana": { + "properties": { + "alert": { + "properties": { + "action_group": { + "type": "keyword" + }, + "ancestors": { + "properties": { + "depth": { + "type": "long" + }, + "id": { + "type": "keyword" + }, + "index": { + "type": "keyword" + }, + "rule": { + "type": "keyword" + }, + "type": { + "type": "keyword" + } + } + }, + "building_block_type": { + "type": "keyword" + }, + "case_ids": { + "type": "keyword" + }, + "depth": { + "type": "long" + }, + "duration": { + "properties": { + "us": { + "type": "long" + } + } + }, + "end": { + "type": "date" + }, + "flapping": { + "type": "boolean" + }, + "flapping_history": { + "type": "boolean" + }, + "group": { + "properties": { + "id": { + "type": "keyword" + }, + "index": { + "type": "integer" + } + } + }, + "instance": { + "properties": { + "id": { + "type": "keyword" + } + } + }, + "last_detected": { + "type": "date" + }, + "maintenance_window_ids": { + "type": "keyword" + }, + "new_terms": { + "type": "keyword" + }, + "original_event": { + "properties": { + "action": { + "type": "keyword" + }, + "agent_id_status": { + "type": "keyword" + }, + "category": { + "type": "keyword" + }, + "code": { + "type": "keyword" + }, + "created": { + "type": "date" + }, + "dataset": { + "type": "keyword" + }, + "duration": { + "type": "keyword" + }, + "end": { + "type": "date" + }, + "hash": { + "type": "keyword" + }, + "id": { + "type": "keyword" + }, + "ingested": { + "type": "date" + }, + "kind": { + "type": "keyword" + }, + "module": { + "type": "keyword" + }, + "original": { + "type": "keyword" + }, + "outcome": { + "type": "keyword" + }, + "provider": { + "type": "keyword" + }, + "reason": { + "type": "keyword" + }, + "reference": { + "type": "keyword" + }, + "risk_score": { + "type": "float" + }, + "risk_score_norm": { + "type": "float" + }, + "sequence": { + "type": "long" + }, + "severity": { + "type": "long" + }, + "start": { + "type": "date" + }, + "timezone": { + "type": "keyword" + }, + "type": { + "type": "keyword" + }, + "url": { + "type": "keyword" + } + } + }, + "original_time": { + "type": "date" + }, + "reason": { + "type": "keyword" + }, + "risk_score": { + "type": "float" + }, + "rule": { + "properties": { + "author": { + "type": "keyword" + }, + "building_block_type": { + "type": "keyword" + }, + "category": { + "type": "keyword" + }, + "consumer": { + "type": "keyword" + }, + "created_at": { + "type": "date" + }, + "created_by": { + "type": "keyword" + }, + "description": { + "type": "keyword" + }, + "enabled": { + "type": "keyword" + }, + "exceptions_list": { + "type": "object" + }, + "execution": { + "properties": { + "uuid": { + "type": "keyword" + } + } + }, + "false_positives": { + "type": "keyword" + }, + "from": { + "type": "keyword" + }, + "immutable": { + "type": "keyword" + }, + "interval": { + "type": "keyword" + }, + "license": { + "type": "keyword" + }, + "max_signals": { + "type": "long" + }, + "name": { + "type": "keyword" + }, + "note": { + "type": "keyword" + }, + "parameters": { + "ignore_above": 4096, + "type": "flattened" + }, + "producer": { + "type": "keyword" + }, + "references": { + "type": "keyword" + }, + "revision": { + "type": "long" + }, + "rule_id": { + "type": "keyword" + }, + "rule_name_override": { + "type": "keyword" + }, + "rule_type_id": { + "type": "keyword" + }, + "tags": { + "type": "keyword" + }, + "threat": { + "properties": { + "framework": { + "type": "keyword" + }, + "tactic": { + "properties": { + "id": { + "type": "keyword" + }, + "name": { + "type": "keyword" + }, + "reference": { + "type": "keyword" + } + } + }, + "technique": { + "properties": { + "id": { + "type": "keyword" + }, + "name": { + "type": "keyword" + }, + "reference": { + "type": "keyword" + }, + "subtechnique": { + "properties": { + "id": { + "type": "keyword" + }, + "name": { + "type": "keyword" + }, + "reference": { + "type": "keyword" + } + } + } + } + } + } + }, + "timeline_id": { + "type": "keyword" + }, + "timeline_title": { + "type": "keyword" + }, + "timestamp_override": { + "type": "keyword" + }, + "to": { + "type": "keyword" + }, + "type": { + "type": "keyword" + }, + "updated_at": { + "type": "date" + }, + "updated_by": { + "type": "keyword" + }, + "uuid": { + "type": "keyword" + }, + "version": { + "type": "keyword" + } + } + }, + "severity": { + "type": "keyword" + }, + "start": { + "type": "date" + }, + "status": { + "type": "keyword" + }, + "suppression": { + "properties": { + "docs_count": { + "type": "long" + }, + "end": { + "type": "date" + }, + "start": { + "type": "date" + }, + "terms": { + "properties": { + "field": { + "type": "keyword" + }, + "value": { + "type": "keyword" + } + } + } + } + }, + "system_status": { + "type": "keyword" + }, + "threshold_result": { + "properties": { + "cardinality": { + "properties": { + "field": { + "type": "keyword" + }, + "value": { + "type": "long" + } + } + }, + "count": { + "type": "long" + }, + "from": { + "type": "date" + }, + "terms": { + "properties": { + "field": { + "type": "keyword" + }, + "value": { + "type": "keyword" + } + } + } + } + }, + "time_range": { + "format": "epoch_millis||strict_date_optional_time", + "type": "date_range" + }, + "url": { + "ignore_above": 2048, + "index": false, + "type": "keyword" + }, + "uuid": { + "type": "keyword" + }, + "workflow_reason": { + "type": "keyword" + }, + "workflow_status": { + "type": "keyword" + }, + "workflow_user": { + "type": "keyword" + } + } + }, + "space_ids": { + "type": "keyword" + }, + "version": { + "type": "version" + } + } + }, + "labels": { + "type": "object" + }, + "log": { + "properties": { + "file": { + "properties": { + "path": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "level": { + "ignore_above": 1024, + "type": "keyword" + }, + "logger": { + "ignore_above": 1024, + "type": "keyword" + }, + "origin": { + "properties": { + "file": { + "properties": { + "line": { + "type": "long" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "function": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "syslog": { + "properties": { + "appname": { + "ignore_above": 1024, + "type": "keyword" + }, + "facility": { + "properties": { + "code": { + "type": "long" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "hostname": { + "ignore_above": 1024, + "type": "keyword" + }, + "msgid": { + "ignore_above": 1024, + "type": "keyword" + }, + "priority": { + "type": "long" + }, + "procid": { + "ignore_above": 1024, + "type": "keyword" + }, + "severity": { + "properties": { + "code": { + "type": "long" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "structured_data": { + "type": "flattened" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "message": { + "type": "match_only_text" + }, + "network": { + "properties": { + "application": { + "ignore_above": 1024, + "type": "keyword" + }, + "bytes": { + "type": "long" + }, + "community_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "direction": { + "ignore_above": 1024, + "type": "keyword" + }, + "forwarded_ip": { + "type": "ip" + }, + "iana_number": { + "ignore_above": 1024, + "type": "keyword" + }, + "inner": { + "properties": { + "vlan": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "packets": { + "type": "long" + }, + "protocol": { + "ignore_above": 1024, + "type": "keyword" + }, + "transport": { + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "vlan": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "observer": { + "properties": { + "egress": { + "properties": { + "interface": { + "properties": { + "alias": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "vlan": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "zone": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "geo": { + "properties": { + "city_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "continent_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "continent_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "country_iso_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "country_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "location": { + "type": "geo_point" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "postal_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "region_iso_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "region_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "timezone": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "hostname": { + "ignore_above": 1024, + "type": "keyword" + }, + "ingress": { + "properties": { + "interface": { + "properties": { + "alias": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "vlan": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "zone": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "ip": { + "type": "ip" + }, + "mac": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "os": { + "properties": { + "family": { + "ignore_above": 1024, + "type": "keyword" + }, + "full": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "kernel": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "platform": { + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "product": { + "ignore_above": 1024, + "type": "keyword" + }, + "serial_number": { + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "vendor": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "orchestrator": { + "properties": { + "api_version": { + "ignore_above": 1024, + "type": "keyword" + }, + "cluster": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "url": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "namespace": { + "ignore_above": 1024, + "type": "keyword" + }, + "organization": { + "ignore_above": 1024, + "type": "keyword" + }, + "resource": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "ip": { + "type": "ip" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "parent": { + "properties": { + "type": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "organization": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "package": { + "properties": { + "architecture": { + "ignore_above": 1024, + "type": "keyword" + }, + "build_version": { + "ignore_above": 1024, + "type": "keyword" + }, + "checksum": { + "ignore_above": 1024, + "type": "keyword" + }, + "description": { + "ignore_above": 1024, + "type": "keyword" + }, + "install_scope": { + "ignore_above": 1024, + "type": "keyword" + }, + "installed": { + "type": "date" + }, + "license": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "path": { + "ignore_above": 1024, + "type": "keyword" + }, + "reference": { + "ignore_above": 1024, + "type": "keyword" + }, + "size": { + "type": "long" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "process": { + "properties": { + "args": { + "ignore_above": 1024, + "type": "keyword" + }, + "args_count": { + "type": "long" + }, + "code_signature": { + "properties": { + "digest_algorithm": { + "ignore_above": 1024, + "type": "keyword" + }, + "exists": { + "type": "boolean" + }, + "signing_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "status": { + "ignore_above": 1024, + "type": "keyword" + }, + "subject_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "team_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "timestamp": { + "type": "date" + }, + "trusted": { + "type": "boolean" + }, + "valid": { + "type": "boolean" + } + } + }, + "command_line": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "type": "wildcard" + }, + "elf": { + "properties": { + "architecture": { + "ignore_above": 1024, + "type": "keyword" + }, + "byte_order": { + "ignore_above": 1024, + "type": "keyword" + }, + "cpu_type": { + "ignore_above": 1024, + "type": "keyword" + }, + "creation_date": { + "type": "date" + }, + "exports": { + "type": "flattened" + }, + "header": { + "properties": { + "abi_version": { + "ignore_above": 1024, + "type": "keyword" + }, + "class": { + "ignore_above": 1024, + "type": "keyword" + }, + "data": { + "ignore_above": 1024, + "type": "keyword" + }, + "entrypoint": { + "type": "long" + }, + "object_version": { + "ignore_above": 1024, + "type": "keyword" + }, + "os_abi": { + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "imports": { + "type": "flattened" + }, + "sections": { + "properties": { + "chi2": { + "type": "long" + }, + "entropy": { + "type": "long" + }, + "flags": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "physical_offset": { + "ignore_above": 1024, + "type": "keyword" + }, + "physical_size": { + "type": "long" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "virtual_address": { + "type": "long" + }, + "virtual_size": { + "type": "long" + } + }, + "type": "nested" + }, + "segments": { + "properties": { + "sections": { + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + } + }, + "type": "nested" + }, + "shared_libraries": { + "ignore_above": 1024, + "type": "keyword" + }, + "telfhash": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "end": { + "type": "date" + }, + "entity_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "entry_leader": { + "properties": { + "args": { + "ignore_above": 1024, + "type": "keyword" + }, + "args_count": { + "type": "long" + }, + "attested_groups": { + "properties": { + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "attested_user": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "command_line": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "type": "wildcard" + }, + "entity_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "entry_meta": { + "properties": { + "source": { + "properties": { + "ip": { + "type": "ip" + } + } + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "executable": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "group": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "interactive": { + "type": "boolean" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "parent": { + "properties": { + "entity_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "pid": { + "type": "long" + }, + "session_leader": { + "properties": { + "entity_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "pid": { + "type": "long" + }, + "start": { + "type": "date" + } + } + }, + "start": { + "type": "date" + } + } + }, + "pid": { + "type": "long" + }, + "real_group": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "real_user": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "same_as_process": { + "type": "boolean" + }, + "saved_group": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "saved_user": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "start": { + "type": "date" + }, + "supplemental_groups": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "tty": { + "properties": { + "char_device": { + "properties": { + "major": { + "type": "long" + }, + "minor": { + "type": "long" + } + } + } + } + }, + "user": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "working_directory": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "env_vars": { + "ignore_above": 1024, + "type": "keyword" + }, + "executable": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "exit_code": { + "type": "long" + }, + "group_leader": { + "properties": { + "args": { + "ignore_above": 1024, + "type": "keyword" + }, + "args_count": { + "type": "long" + }, + "command_line": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "type": "wildcard" + }, + "entity_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "executable": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "group": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "interactive": { + "type": "boolean" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "pid": { + "type": "long" + }, + "real_group": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "real_user": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "same_as_process": { + "type": "boolean" + }, + "saved_group": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "saved_user": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "start": { + "type": "date" + }, + "supplemental_groups": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "tty": { + "properties": { + "char_device": { + "properties": { + "major": { + "type": "long" + }, + "minor": { + "type": "long" + } + } + } + } + }, + "user": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "working_directory": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "hash": { + "properties": { + "md5": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha1": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha256": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha384": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha512": { + "ignore_above": 1024, + "type": "keyword" + }, + "ssdeep": { + "ignore_above": 1024, + "type": "keyword" + }, + "tlsh": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "interactive": { + "type": "boolean" + }, + "io": { + "properties": { + "bytes_skipped": { + "properties": { + "length": { + "type": "long" + }, + "offset": { + "type": "long" + } + } + }, + "max_bytes_per_process_exceeded": { + "type": "boolean" + }, + "text": { + "type": "wildcard" + }, + "total_bytes_captured": { + "type": "long" + }, + "total_bytes_skipped": { + "type": "long" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "parent": { + "properties": { + "args": { + "ignore_above": 1024, + "type": "keyword" + }, + "args_count": { + "type": "long" + }, + "code_signature": { + "properties": { + "digest_algorithm": { + "ignore_above": 1024, + "type": "keyword" + }, + "exists": { + "type": "boolean" + }, + "signing_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "status": { + "ignore_above": 1024, + "type": "keyword" + }, + "subject_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "team_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "timestamp": { + "type": "date" + }, + "trusted": { + "type": "boolean" + }, + "valid": { + "type": "boolean" + } + } + }, + "command_line": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "type": "wildcard" + }, + "elf": { + "properties": { + "architecture": { + "ignore_above": 1024, + "type": "keyword" + }, + "byte_order": { + "ignore_above": 1024, + "type": "keyword" + }, + "cpu_type": { + "ignore_above": 1024, + "type": "keyword" + }, + "creation_date": { + "type": "date" + }, + "exports": { + "type": "flattened" + }, + "header": { + "properties": { + "abi_version": { + "ignore_above": 1024, + "type": "keyword" + }, + "class": { + "ignore_above": 1024, + "type": "keyword" + }, + "data": { + "ignore_above": 1024, + "type": "keyword" + }, + "entrypoint": { + "type": "long" + }, + "object_version": { + "ignore_above": 1024, + "type": "keyword" + }, + "os_abi": { + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "imports": { + "type": "flattened" + }, + "sections": { + "properties": { + "chi2": { + "type": "long" + }, + "entropy": { + "type": "long" + }, + "flags": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "physical_offset": { + "ignore_above": 1024, + "type": "keyword" + }, + "physical_size": { + "type": "long" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "virtual_address": { + "type": "long" + }, + "virtual_size": { + "type": "long" + } + }, + "type": "nested" + }, + "segments": { + "properties": { + "sections": { + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + } + }, + "type": "nested" + }, + "shared_libraries": { + "ignore_above": 1024, + "type": "keyword" + }, + "telfhash": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "end": { + "type": "date" + }, + "entity_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "executable": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "exit_code": { + "type": "long" + }, + "group": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "group_leader": { + "properties": { + "entity_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "pid": { + "type": "long" + }, + "start": { + "type": "date" + } + } + }, + "hash": { + "properties": { + "md5": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha1": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha256": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha384": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha512": { + "ignore_above": 1024, + "type": "keyword" + }, + "ssdeep": { + "ignore_above": 1024, + "type": "keyword" + }, + "tlsh": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "interactive": { + "type": "boolean" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "pe": { + "properties": { + "architecture": { + "ignore_above": 1024, + "type": "keyword" + }, + "company": { + "ignore_above": 1024, + "type": "keyword" + }, + "description": { + "ignore_above": 1024, + "type": "keyword" + }, + "file_version": { + "ignore_above": 1024, + "type": "keyword" + }, + "imphash": { + "ignore_above": 1024, + "type": "keyword" + }, + "original_file_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "pehash": { + "ignore_above": 1024, + "type": "keyword" + }, + "product": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "pgid": { + "type": "long" + }, + "pid": { + "type": "long" + }, + "real_group": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "real_user": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "saved_group": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "saved_user": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "start": { + "type": "date" + }, + "supplemental_groups": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "thread": { + "properties": { + "id": { + "type": "long" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "title": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "tty": { + "properties": { + "char_device": { + "properties": { + "major": { + "type": "long" + }, + "minor": { + "type": "long" + } + } + } + } + }, + "uptime": { + "type": "long" + }, + "user": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "working_directory": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "pe": { + "properties": { + "architecture": { + "ignore_above": 1024, + "type": "keyword" + }, + "company": { + "ignore_above": 1024, + "type": "keyword" + }, + "description": { + "ignore_above": 1024, + "type": "keyword" + }, + "file_version": { + "ignore_above": 1024, + "type": "keyword" + }, + "imphash": { + "ignore_above": 1024, + "type": "keyword" + }, + "original_file_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "pehash": { + "ignore_above": 1024, + "type": "keyword" + }, + "product": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "pgid": { + "type": "long" + }, + "pid": { + "type": "long" + }, + "previous": { + "properties": { + "args": { + "ignore_above": 1024, + "type": "keyword" + }, + "args_count": { + "type": "long" + }, + "executable": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "real_group": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "real_user": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "saved_group": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "saved_user": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "session_leader": { + "properties": { + "args": { + "ignore_above": 1024, + "type": "keyword" + }, + "args_count": { + "type": "long" + }, + "command_line": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "type": "wildcard" + }, + "entity_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "executable": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "group": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "interactive": { + "type": "boolean" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "parent": { + "properties": { + "entity_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "pid": { + "type": "long" + }, + "session_leader": { + "properties": { + "entity_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "pid": { + "type": "long" + }, + "start": { + "type": "date" + } + } + }, + "start": { + "type": "date" + } + } + }, + "pid": { + "type": "long" + }, + "real_group": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "real_user": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "same_as_process": { + "type": "boolean" + }, + "saved_group": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "saved_user": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "start": { + "type": "date" + }, + "supplemental_groups": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "tty": { + "properties": { + "char_device": { + "properties": { + "major": { + "type": "long" + }, + "minor": { + "type": "long" + } + } + } + } + }, + "user": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "working_directory": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "start": { + "type": "date" + }, + "supplemental_groups": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "thread": { + "properties": { + "id": { + "type": "long" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "title": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "tty": { + "properties": { + "char_device": { + "properties": { + "major": { + "type": "long" + }, + "minor": { + "type": "long" + } + } + }, + "columns": { + "type": "long" + }, + "rows": { + "type": "long" + } + } + }, + "uptime": { + "type": "long" + }, + "user": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "working_directory": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "registry": { + "properties": { + "data": { + "properties": { + "bytes": { + "ignore_above": 1024, + "type": "keyword" + }, + "strings": { + "type": "wildcard" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "hive": { + "ignore_above": 1024, + "type": "keyword" + }, + "key": { + "ignore_above": 1024, + "type": "keyword" + }, + "path": { + "ignore_above": 1024, + "type": "keyword" + }, + "value": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "related": { + "properties": { + "hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "hosts": { + "ignore_above": 1024, + "type": "keyword" + }, + "ip": { + "type": "ip" + }, + "user": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "rule": { + "properties": { + "author": { + "ignore_above": 1024, + "type": "keyword" + }, + "category": { + "ignore_above": 1024, + "type": "keyword" + }, + "description": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "license": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "reference": { + "ignore_above": 1024, + "type": "keyword" + }, + "ruleset": { + "ignore_above": 1024, + "type": "keyword" + }, + "uuid": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "server": { + "properties": { + "address": { + "ignore_above": 1024, + "type": "keyword" + }, + "as": { + "properties": { + "number": { + "type": "long" + }, + "organization": { + "properties": { + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "bytes": { + "type": "long" + }, + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "geo": { + "properties": { + "city_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "continent_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "continent_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "country_iso_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "country_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "location": { + "type": "geo_point" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "postal_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "region_iso_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "region_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "timezone": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "ip": { + "type": "ip" + }, + "mac": { + "ignore_above": 1024, + "type": "keyword" + }, + "nat": { + "properties": { + "ip": { + "type": "ip" + }, + "port": { + "type": "long" + } + } + }, + "packets": { + "type": "long" + }, + "port": { + "type": "long" + }, + "registered_domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "subdomain": { + "ignore_above": 1024, + "type": "keyword" + }, + "top_level_domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "user": { + "properties": { + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "email": { + "ignore_above": 1024, + "type": "keyword" + }, + "full_name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "group": { + "properties": { + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "roles": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "service": { + "properties": { + "address": { + "ignore_above": 1024, + "type": "keyword" + }, + "environment": { + "ignore_above": 1024, + "type": "keyword" + }, + "ephemeral_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "node": { + "properties": { + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "role": { + "ignore_above": 1024, + "type": "keyword" + }, + "roles": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "origin": { + "properties": { + "address": { + "ignore_above": 1024, + "type": "keyword" + }, + "environment": { + "ignore_above": 1024, + "type": "keyword" + }, + "ephemeral_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "node": { + "properties": { + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "role": { + "ignore_above": 1024, + "type": "keyword" + }, + "roles": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "state": { + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "state": { + "ignore_above": 1024, + "type": "keyword" + }, + "target": { + "properties": { + "address": { + "ignore_above": 1024, + "type": "keyword" + }, + "environment": { + "ignore_above": 1024, + "type": "keyword" + }, + "ephemeral_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "node": { + "properties": { + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "role": { + "ignore_above": 1024, + "type": "keyword" + }, + "roles": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "state": { + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "signal": { + "properties": { + "ancestors": { + "properties": { + "depth": { + "path": "kibana.alert.ancestors.depth", + "type": "alias" + }, + "id": { + "path": "kibana.alert.ancestors.id", + "type": "alias" + }, + "index": { + "path": "kibana.alert.ancestors.index", + "type": "alias" + }, + "type": { + "path": "kibana.alert.ancestors.type", + "type": "alias" + } + } + }, + "depth": { + "path": "kibana.alert.depth", + "type": "alias" + }, + "group": { + "properties": { + "id": { + "path": "kibana.alert.group.id", + "type": "alias" + }, + "index": { + "path": "kibana.alert.group.index", + "type": "alias" + } + } + }, + "original_event": { + "properties": { + "action": { + "path": "kibana.alert.original_event.action", + "type": "alias" + }, + "category": { + "path": "kibana.alert.original_event.category", + "type": "alias" + }, + "code": { + "path": "kibana.alert.original_event.code", + "type": "alias" + }, + "created": { + "path": "kibana.alert.original_event.created", + "type": "alias" + }, + "dataset": { + "path": "kibana.alert.original_event.dataset", + "type": "alias" + }, + "duration": { + "path": "kibana.alert.original_event.duration", + "type": "alias" + }, + "end": { + "path": "kibana.alert.original_event.end", + "type": "alias" + }, + "hash": { + "path": "kibana.alert.original_event.hash", + "type": "alias" + }, + "id": { + "path": "kibana.alert.original_event.id", + "type": "alias" + }, + "kind": { + "path": "kibana.alert.original_event.kind", + "type": "alias" + }, + "module": { + "path": "kibana.alert.original_event.module", + "type": "alias" + }, + "outcome": { + "path": "kibana.alert.original_event.outcome", + "type": "alias" + }, + "provider": { + "path": "kibana.alert.original_event.provider", + "type": "alias" + }, + "reason": { + "path": "kibana.alert.original_event.reason", + "type": "alias" + }, + "risk_score": { + "path": "kibana.alert.original_event.risk_score", + "type": "alias" + }, + "risk_score_norm": { + "path": "kibana.alert.original_event.risk_score_norm", + "type": "alias" + }, + "sequence": { + "path": "kibana.alert.original_event.sequence", + "type": "alias" + }, + "severity": { + "path": "kibana.alert.original_event.severity", + "type": "alias" + }, + "start": { + "path": "kibana.alert.original_event.start", + "type": "alias" + }, + "timezone": { + "path": "kibana.alert.original_event.timezone", + "type": "alias" + }, + "type": { + "path": "kibana.alert.original_event.type", + "type": "alias" + } + } + }, + "original_time": { + "path": "kibana.alert.original_time", + "type": "alias" + }, + "reason": { + "path": "kibana.alert.reason", + "type": "alias" + }, + "rule": { + "properties": { + "author": { + "path": "kibana.alert.rule.author", + "type": "alias" + }, + "building_block_type": { + "path": "kibana.alert.building_block_type", + "type": "alias" + }, + "created_at": { + "path": "kibana.alert.rule.created_at", + "type": "alias" + }, + "created_by": { + "path": "kibana.alert.rule.created_by", + "type": "alias" + }, + "description": { + "path": "kibana.alert.rule.description", + "type": "alias" + }, + "enabled": { + "path": "kibana.alert.rule.enabled", + "type": "alias" + }, + "false_positives": { + "path": "kibana.alert.rule.false_positives", + "type": "alias" + }, + "from": { + "path": "kibana.alert.rule.from", + "type": "alias" + }, + "id": { + "path": "kibana.alert.rule.uuid", + "type": "alias" + }, + "immutable": { + "path": "kibana.alert.rule.immutable", + "type": "alias" + }, + "interval": { + "path": "kibana.alert.rule.interval", + "type": "alias" + }, + "license": { + "path": "kibana.alert.rule.license", + "type": "alias" + }, + "max_signals": { + "path": "kibana.alert.rule.max_signals", + "type": "alias" + }, + "name": { + "path": "kibana.alert.rule.name", + "type": "alias" + }, + "note": { + "path": "kibana.alert.rule.note", + "type": "alias" + }, + "references": { + "path": "kibana.alert.rule.references", + "type": "alias" + }, + "risk_score": { + "path": "kibana.alert.risk_score", + "type": "alias" + }, + "rule_id": { + "path": "kibana.alert.rule.rule_id", + "type": "alias" + }, + "rule_name_override": { + "path": "kibana.alert.rule.rule_name_override", + "type": "alias" + }, + "severity": { + "path": "kibana.alert.severity", + "type": "alias" + }, + "tags": { + "path": "kibana.alert.rule.tags", + "type": "alias" + }, + "threat": { + "properties": { + "framework": { + "path": "kibana.alert.rule.threat.framework", + "type": "alias" + }, + "tactic": { + "properties": { + "id": { + "path": "kibana.alert.rule.threat.tactic.id", + "type": "alias" + }, + "name": { + "path": "kibana.alert.rule.threat.tactic.name", + "type": "alias" + }, + "reference": { + "path": "kibana.alert.rule.threat.tactic.reference", + "type": "alias" + } + } + }, + "technique": { + "properties": { + "id": { + "path": "kibana.alert.rule.threat.technique.id", + "type": "alias" + }, + "name": { + "path": "kibana.alert.rule.threat.technique.name", + "type": "alias" + }, + "reference": { + "path": "kibana.alert.rule.threat.technique.reference", + "type": "alias" + }, + "subtechnique": { + "properties": { + "id": { + "path": "kibana.alert.rule.threat.technique.subtechnique.id", + "type": "alias" + }, + "name": { + "path": "kibana.alert.rule.threat.technique.subtechnique.name", + "type": "alias" + }, + "reference": { + "path": "kibana.alert.rule.threat.technique.subtechnique.reference", + "type": "alias" + } + } + } + } + } + } + }, + "timeline_id": { + "path": "kibana.alert.rule.timeline_id", + "type": "alias" + }, + "timeline_title": { + "path": "kibana.alert.rule.timeline_title", + "type": "alias" + }, + "timestamp_override": { + "path": "kibana.alert.rule.timestamp_override", + "type": "alias" + }, + "to": { + "path": "kibana.alert.rule.to", + "type": "alias" + }, + "type": { + "path": "kibana.alert.rule.type", + "type": "alias" + }, + "updated_at": { + "path": "kibana.alert.rule.updated_at", + "type": "alias" + }, + "updated_by": { + "path": "kibana.alert.rule.updated_by", + "type": "alias" + }, + "version": { + "path": "kibana.alert.rule.version", + "type": "alias" + } + } + }, + "status": { + "path": "kibana.alert.workflow_status", + "type": "alias" + }, + "threshold_result": { + "properties": { + "cardinality": { + "properties": { + "field": { + "path": "kibana.alert.threshold_result.cardinality.field", + "type": "alias" + }, + "value": { + "path": "kibana.alert.threshold_result.cardinality.value", + "type": "alias" + } + } + }, + "count": { + "path": "kibana.alert.threshold_result.count", + "type": "alias" + }, + "from": { + "path": "kibana.alert.threshold_result.from", + "type": "alias" + }, + "terms": { + "properties": { + "field": { + "path": "kibana.alert.threshold_result.terms.field", + "type": "alias" + }, + "value": { + "path": "kibana.alert.threshold_result.terms.value", + "type": "alias" + } + } + } + } + } + } + }, + "source": { + "properties": { + "address": { + "ignore_above": 1024, + "type": "keyword" + }, + "as": { + "properties": { + "number": { + "type": "long" + }, + "organization": { + "properties": { + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "bytes": { + "type": "long" + }, + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "geo": { + "properties": { + "city_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "continent_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "continent_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "country_iso_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "country_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "location": { + "type": "geo_point" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "postal_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "region_iso_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "region_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "timezone": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "ip": { + "type": "ip" + }, + "mac": { + "ignore_above": 1024, + "type": "keyword" + }, + "nat": { + "properties": { + "ip": { + "type": "ip" + }, + "port": { + "type": "long" + } + } + }, + "packets": { + "type": "long" + }, + "port": { + "type": "long" + }, + "registered_domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "subdomain": { + "ignore_above": 1024, + "type": "keyword" + }, + "top_level_domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "user": { + "properties": { + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "email": { + "ignore_above": 1024, + "type": "keyword" + }, + "full_name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "group": { + "properties": { + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "roles": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "span": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "tags": { + "type": "keyword" + }, + "threat": { + "properties": { + "enrichments": { + "properties": { + "indicator": { + "properties": { + "as": { + "properties": { + "number": { + "type": "long" + }, + "organization": { + "properties": { + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "confidence": { + "ignore_above": 1024, + "type": "keyword" + }, + "description": { + "ignore_above": 1024, + "type": "keyword" + }, + "email": { + "properties": { + "address": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "file": { + "properties": { + "accessed": { + "type": "date" + }, + "attributes": { + "ignore_above": 1024, + "type": "keyword" + }, + "code_signature": { + "properties": { + "digest_algorithm": { + "ignore_above": 1024, + "type": "keyword" + }, + "exists": { + "type": "boolean" + }, + "signing_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "status": { + "ignore_above": 1024, + "type": "keyword" + }, + "subject_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "team_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "timestamp": { + "type": "date" + }, + "trusted": { + "type": "boolean" + }, + "valid": { + "type": "boolean" + } + } + }, + "created": { + "type": "date" + }, + "ctime": { + "type": "date" + }, + "device": { + "ignore_above": 1024, + "type": "keyword" + }, + "directory": { + "ignore_above": 1024, + "type": "keyword" + }, + "drive_letter": { + "ignore_above": 1, + "type": "keyword" + }, + "elf": { + "properties": { + "architecture": { + "ignore_above": 1024, + "type": "keyword" + }, + "byte_order": { + "ignore_above": 1024, + "type": "keyword" + }, + "cpu_type": { + "ignore_above": 1024, + "type": "keyword" + }, + "creation_date": { + "type": "date" + }, + "exports": { + "type": "flattened" + }, + "header": { + "properties": { + "abi_version": { + "ignore_above": 1024, + "type": "keyword" + }, + "class": { + "ignore_above": 1024, + "type": "keyword" + }, + "data": { + "ignore_above": 1024, + "type": "keyword" + }, + "entrypoint": { + "type": "long" + }, + "object_version": { + "ignore_above": 1024, + "type": "keyword" + }, + "os_abi": { + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "imports": { + "type": "flattened" + }, + "sections": { + "properties": { + "chi2": { + "type": "long" + }, + "entropy": { + "type": "long" + }, + "flags": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "physical_offset": { + "ignore_above": 1024, + "type": "keyword" + }, + "physical_size": { + "type": "long" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "virtual_address": { + "type": "long" + }, + "virtual_size": { + "type": "long" + } + }, + "type": "nested" + }, + "segments": { + "properties": { + "sections": { + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + } + }, + "type": "nested" + }, + "shared_libraries": { + "ignore_above": 1024, + "type": "keyword" + }, + "telfhash": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "extension": { + "ignore_above": 1024, + "type": "keyword" + }, + "fork_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "gid": { + "ignore_above": 1024, + "type": "keyword" + }, + "group": { + "ignore_above": 1024, + "type": "keyword" + }, + "hash": { + "properties": { + "md5": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha1": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha256": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha384": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha512": { + "ignore_above": 1024, + "type": "keyword" + }, + "ssdeep": { + "ignore_above": 1024, + "type": "keyword" + }, + "tlsh": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "inode": { + "ignore_above": 1024, + "type": "keyword" + }, + "mime_type": { + "ignore_above": 1024, + "type": "keyword" + }, + "mode": { + "ignore_above": 1024, + "type": "keyword" + }, + "mtime": { + "type": "date" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "owner": { + "ignore_above": 1024, + "type": "keyword" + }, + "path": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "pe": { + "properties": { + "architecture": { + "ignore_above": 1024, + "type": "keyword" + }, + "company": { + "ignore_above": 1024, + "type": "keyword" + }, + "description": { + "ignore_above": 1024, + "type": "keyword" + }, + "file_version": { + "ignore_above": 1024, + "type": "keyword" + }, + "imphash": { + "ignore_above": 1024, + "type": "keyword" + }, + "original_file_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "pehash": { + "ignore_above": 1024, + "type": "keyword" + }, + "product": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "size": { + "type": "long" + }, + "target_path": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "uid": { + "ignore_above": 1024, + "type": "keyword" + }, + "x509": { + "properties": { + "alternative_names": { + "ignore_above": 1024, + "type": "keyword" + }, + "issuer": { + "properties": { + "common_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "country": { + "ignore_above": 1024, + "type": "keyword" + }, + "distinguished_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "locality": { + "ignore_above": 1024, + "type": "keyword" + }, + "organization": { + "ignore_above": 1024, + "type": "keyword" + }, + "organizational_unit": { + "ignore_above": 1024, + "type": "keyword" + }, + "state_or_province": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "not_after": { + "type": "date" + }, + "not_before": { + "type": "date" + }, + "public_key_algorithm": { + "ignore_above": 1024, + "type": "keyword" + }, + "public_key_curve": { + "ignore_above": 1024, + "type": "keyword" + }, + "public_key_exponent": { + "type": "long" + }, + "public_key_size": { + "type": "long" + }, + "serial_number": { + "ignore_above": 1024, + "type": "keyword" + }, + "signature_algorithm": { + "ignore_above": 1024, + "type": "keyword" + }, + "subject": { + "properties": { + "common_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "country": { + "ignore_above": 1024, + "type": "keyword" + }, + "distinguished_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "locality": { + "ignore_above": 1024, + "type": "keyword" + }, + "organization": { + "ignore_above": 1024, + "type": "keyword" + }, + "organizational_unit": { + "ignore_above": 1024, + "type": "keyword" + }, + "state_or_province": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "version_number": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "first_seen": { + "type": "date" + }, + "geo": { + "properties": { + "city_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "continent_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "continent_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "country_iso_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "country_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "location": { + "type": "geo_point" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "postal_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "region_iso_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "region_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "timezone": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "ip": { + "type": "ip" + }, + "last_seen": { + "type": "date" + }, + "marking": { + "properties": { + "tlp": { + "ignore_above": 1024, + "type": "keyword" + }, + "tlp_version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "modified_at": { + "type": "date" + }, + "port": { + "type": "long" + }, + "provider": { + "ignore_above": 1024, + "type": "keyword" + }, + "reference": { + "ignore_above": 1024, + "type": "keyword" + }, + "registry": { + "properties": { + "data": { + "properties": { + "bytes": { + "ignore_above": 1024, + "type": "keyword" + }, + "strings": { + "type": "wildcard" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "hive": { + "ignore_above": 1024, + "type": "keyword" + }, + "key": { + "ignore_above": 1024, + "type": "keyword" + }, + "path": { + "ignore_above": 1024, + "type": "keyword" + }, + "value": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "scanner_stats": { + "type": "long" + }, + "sightings": { + "type": "long" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "url": { + "properties": { + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "extension": { + "ignore_above": 1024, + "type": "keyword" + }, + "fragment": { + "ignore_above": 1024, + "type": "keyword" + }, + "full": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "type": "wildcard" + }, + "original": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "type": "wildcard" + }, + "password": { + "ignore_above": 1024, + "type": "keyword" + }, + "path": { + "type": "wildcard" + }, + "port": { + "type": "long" + }, + "query": { + "ignore_above": 1024, + "type": "keyword" + }, + "registered_domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "scheme": { + "ignore_above": 1024, + "type": "keyword" + }, + "subdomain": { + "ignore_above": 1024, + "type": "keyword" + }, + "top_level_domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "username": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "x509": { + "properties": { + "alternative_names": { + "ignore_above": 1024, + "type": "keyword" + }, + "issuer": { + "properties": { + "common_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "country": { + "ignore_above": 1024, + "type": "keyword" + }, + "distinguished_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "locality": { + "ignore_above": 1024, + "type": "keyword" + }, + "organization": { + "ignore_above": 1024, + "type": "keyword" + }, + "organizational_unit": { + "ignore_above": 1024, + "type": "keyword" + }, + "state_or_province": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "not_after": { + "type": "date" + }, + "not_before": { + "type": "date" + }, + "public_key_algorithm": { + "ignore_above": 1024, + "type": "keyword" + }, + "public_key_curve": { + "ignore_above": 1024, + "type": "keyword" + }, + "public_key_exponent": { + "type": "long" + }, + "public_key_size": { + "type": "long" + }, + "serial_number": { + "ignore_above": 1024, + "type": "keyword" + }, + "signature_algorithm": { + "ignore_above": 1024, + "type": "keyword" + }, + "subject": { + "properties": { + "common_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "country": { + "ignore_above": 1024, + "type": "keyword" + }, + "distinguished_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "locality": { + "ignore_above": 1024, + "type": "keyword" + }, + "organization": { + "ignore_above": 1024, + "type": "keyword" + }, + "organizational_unit": { + "ignore_above": 1024, + "type": "keyword" + }, + "state_or_province": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "version_number": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "matched": { + "properties": { + "atomic": { + "ignore_above": 1024, + "type": "keyword" + }, + "field": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "index": { + "ignore_above": 1024, + "type": "keyword" + }, + "occurred": { + "type": "date" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + }, + "type": "nested" + }, + "feed": { + "properties": { + "dashboard_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "description": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "reference": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "framework": { + "ignore_above": 1024, + "type": "keyword" + }, + "group": { + "properties": { + "alias": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "reference": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "indicator": { + "properties": { + "as": { + "properties": { + "number": { + "type": "long" + }, + "organization": { + "properties": { + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "confidence": { + "ignore_above": 1024, + "type": "keyword" + }, + "description": { + "ignore_above": 1024, + "type": "keyword" + }, + "email": { + "properties": { + "address": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "file": { + "properties": { + "accessed": { + "type": "date" + }, + "attributes": { + "ignore_above": 1024, + "type": "keyword" + }, + "code_signature": { + "properties": { + "digest_algorithm": { + "ignore_above": 1024, + "type": "keyword" + }, + "exists": { + "type": "boolean" + }, + "signing_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "status": { + "ignore_above": 1024, + "type": "keyword" + }, + "subject_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "team_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "timestamp": { + "type": "date" + }, + "trusted": { + "type": "boolean" + }, + "valid": { + "type": "boolean" + } + } + }, + "created": { + "type": "date" + }, + "ctime": { + "type": "date" + }, + "device": { + "ignore_above": 1024, + "type": "keyword" + }, + "directory": { + "ignore_above": 1024, + "type": "keyword" + }, + "drive_letter": { + "ignore_above": 1, + "type": "keyword" + }, + "elf": { + "properties": { + "architecture": { + "ignore_above": 1024, + "type": "keyword" + }, + "byte_order": { + "ignore_above": 1024, + "type": "keyword" + }, + "cpu_type": { + "ignore_above": 1024, + "type": "keyword" + }, + "creation_date": { + "type": "date" + }, + "exports": { + "type": "flattened" + }, + "header": { + "properties": { + "abi_version": { + "ignore_above": 1024, + "type": "keyword" + }, + "class": { + "ignore_above": 1024, + "type": "keyword" + }, + "data": { + "ignore_above": 1024, + "type": "keyword" + }, + "entrypoint": { + "type": "long" + }, + "object_version": { + "ignore_above": 1024, + "type": "keyword" + }, + "os_abi": { + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "imports": { + "type": "flattened" + }, + "sections": { + "properties": { + "chi2": { + "type": "long" + }, + "entropy": { + "type": "long" + }, + "flags": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "physical_offset": { + "ignore_above": 1024, + "type": "keyword" + }, + "physical_size": { + "type": "long" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "virtual_address": { + "type": "long" + }, + "virtual_size": { + "type": "long" + } + }, + "type": "nested" + }, + "segments": { + "properties": { + "sections": { + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + } + }, + "type": "nested" + }, + "shared_libraries": { + "ignore_above": 1024, + "type": "keyword" + }, + "telfhash": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "extension": { + "ignore_above": 1024, + "type": "keyword" + }, + "fork_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "gid": { + "ignore_above": 1024, + "type": "keyword" + }, + "group": { + "ignore_above": 1024, + "type": "keyword" + }, + "hash": { + "properties": { + "md5": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha1": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha256": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha384": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha512": { + "ignore_above": 1024, + "type": "keyword" + }, + "ssdeep": { + "ignore_above": 1024, + "type": "keyword" + }, + "tlsh": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "inode": { + "ignore_above": 1024, + "type": "keyword" + }, + "mime_type": { + "ignore_above": 1024, + "type": "keyword" + }, + "mode": { + "ignore_above": 1024, + "type": "keyword" + }, + "mtime": { + "type": "date" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "owner": { + "ignore_above": 1024, + "type": "keyword" + }, + "path": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "pe": { + "properties": { + "architecture": { + "ignore_above": 1024, + "type": "keyword" + }, + "company": { + "ignore_above": 1024, + "type": "keyword" + }, + "description": { + "ignore_above": 1024, + "type": "keyword" + }, + "file_version": { + "ignore_above": 1024, + "type": "keyword" + }, + "imphash": { + "ignore_above": 1024, + "type": "keyword" + }, + "original_file_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "pehash": { + "ignore_above": 1024, + "type": "keyword" + }, + "product": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "size": { + "type": "long" + }, + "target_path": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "uid": { + "ignore_above": 1024, + "type": "keyword" + }, + "x509": { + "properties": { + "alternative_names": { + "ignore_above": 1024, + "type": "keyword" + }, + "issuer": { + "properties": { + "common_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "country": { + "ignore_above": 1024, + "type": "keyword" + }, + "distinguished_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "locality": { + "ignore_above": 1024, + "type": "keyword" + }, + "organization": { + "ignore_above": 1024, + "type": "keyword" + }, + "organizational_unit": { + "ignore_above": 1024, + "type": "keyword" + }, + "state_or_province": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "not_after": { + "type": "date" + }, + "not_before": { + "type": "date" + }, + "public_key_algorithm": { + "ignore_above": 1024, + "type": "keyword" + }, + "public_key_curve": { + "ignore_above": 1024, + "type": "keyword" + }, + "public_key_exponent": { + "type": "long" + }, + "public_key_size": { + "type": "long" + }, + "serial_number": { + "ignore_above": 1024, + "type": "keyword" + }, + "signature_algorithm": { + "ignore_above": 1024, + "type": "keyword" + }, + "subject": { + "properties": { + "common_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "country": { + "ignore_above": 1024, + "type": "keyword" + }, + "distinguished_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "locality": { + "ignore_above": 1024, + "type": "keyword" + }, + "organization": { + "ignore_above": 1024, + "type": "keyword" + }, + "organizational_unit": { + "ignore_above": 1024, + "type": "keyword" + }, + "state_or_province": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "version_number": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "first_seen": { + "type": "date" + }, + "geo": { + "properties": { + "city_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "continent_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "continent_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "country_iso_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "country_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "location": { + "type": "geo_point" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "postal_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "region_iso_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "region_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "timezone": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "ip": { + "type": "ip" + }, + "last_seen": { + "type": "date" + }, + "marking": { + "properties": { + "tlp": { + "ignore_above": 1024, + "type": "keyword" + }, + "tlp_version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "modified_at": { + "type": "date" + }, + "port": { + "type": "long" + }, + "provider": { + "ignore_above": 1024, + "type": "keyword" + }, + "reference": { + "ignore_above": 1024, + "type": "keyword" + }, + "registry": { + "properties": { + "data": { + "properties": { + "bytes": { + "ignore_above": 1024, + "type": "keyword" + }, + "strings": { + "type": "wildcard" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "hive": { + "ignore_above": 1024, + "type": "keyword" + }, + "key": { + "ignore_above": 1024, + "type": "keyword" + }, + "path": { + "ignore_above": 1024, + "type": "keyword" + }, + "value": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "scanner_stats": { + "type": "long" + }, + "sightings": { + "type": "long" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "url": { + "properties": { + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "extension": { + "ignore_above": 1024, + "type": "keyword" + }, + "fragment": { + "ignore_above": 1024, + "type": "keyword" + }, + "full": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "type": "wildcard" + }, + "original": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "type": "wildcard" + }, + "password": { + "ignore_above": 1024, + "type": "keyword" + }, + "path": { + "type": "wildcard" + }, + "port": { + "type": "long" + }, + "query": { + "ignore_above": 1024, + "type": "keyword" + }, + "registered_domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "scheme": { + "ignore_above": 1024, + "type": "keyword" + }, + "subdomain": { + "ignore_above": 1024, + "type": "keyword" + }, + "top_level_domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "username": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "x509": { + "properties": { + "alternative_names": { + "ignore_above": 1024, + "type": "keyword" + }, + "issuer": { + "properties": { + "common_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "country": { + "ignore_above": 1024, + "type": "keyword" + }, + "distinguished_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "locality": { + "ignore_above": 1024, + "type": "keyword" + }, + "organization": { + "ignore_above": 1024, + "type": "keyword" + }, + "organizational_unit": { + "ignore_above": 1024, + "type": "keyword" + }, + "state_or_province": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "not_after": { + "type": "date" + }, + "not_before": { + "type": "date" + }, + "public_key_algorithm": { + "ignore_above": 1024, + "type": "keyword" + }, + "public_key_curve": { + "ignore_above": 1024, + "type": "keyword" + }, + "public_key_exponent": { + "type": "long" + }, + "public_key_size": { + "type": "long" + }, + "serial_number": { + "ignore_above": 1024, + "type": "keyword" + }, + "signature_algorithm": { + "ignore_above": 1024, + "type": "keyword" + }, + "subject": { + "properties": { + "common_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "country": { + "ignore_above": 1024, + "type": "keyword" + }, + "distinguished_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "locality": { + "ignore_above": 1024, + "type": "keyword" + }, + "organization": { + "ignore_above": 1024, + "type": "keyword" + }, + "organizational_unit": { + "ignore_above": 1024, + "type": "keyword" + }, + "state_or_province": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "version_number": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "software": { + "properties": { + "alias": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "platforms": { + "ignore_above": 1024, + "type": "keyword" + }, + "reference": { + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "tactic": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "reference": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "technique": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "reference": { + "ignore_above": 1024, + "type": "keyword" + }, + "subtechnique": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "reference": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + } + } + }, + "tls": { + "properties": { + "cipher": { + "ignore_above": 1024, + "type": "keyword" + }, + "client": { + "properties": { + "certificate": { + "ignore_above": 1024, + "type": "keyword" + }, + "certificate_chain": { + "ignore_above": 1024, + "type": "keyword" + }, + "hash": { + "properties": { + "md5": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha1": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha256": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "issuer": { + "ignore_above": 1024, + "type": "keyword" + }, + "ja3": { + "ignore_above": 1024, + "type": "keyword" + }, + "not_after": { + "type": "date" + }, + "not_before": { + "type": "date" + }, + "server_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "subject": { + "ignore_above": 1024, + "type": "keyword" + }, + "supported_ciphers": { + "ignore_above": 1024, + "type": "keyword" + }, + "x509": { + "properties": { + "alternative_names": { + "ignore_above": 1024, + "type": "keyword" + }, + "issuer": { + "properties": { + "common_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "country": { + "ignore_above": 1024, + "type": "keyword" + }, + "distinguished_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "locality": { + "ignore_above": 1024, + "type": "keyword" + }, + "organization": { + "ignore_above": 1024, + "type": "keyword" + }, + "organizational_unit": { + "ignore_above": 1024, + "type": "keyword" + }, + "state_or_province": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "not_after": { + "type": "date" + }, + "not_before": { + "type": "date" + }, + "public_key_algorithm": { + "ignore_above": 1024, + "type": "keyword" + }, + "public_key_curve": { + "ignore_above": 1024, + "type": "keyword" + }, + "public_key_exponent": { + "type": "long" + }, + "public_key_size": { + "type": "long" + }, + "serial_number": { + "ignore_above": 1024, + "type": "keyword" + }, + "signature_algorithm": { + "ignore_above": 1024, + "type": "keyword" + }, + "subject": { + "properties": { + "common_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "country": { + "ignore_above": 1024, + "type": "keyword" + }, + "distinguished_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "locality": { + "ignore_above": 1024, + "type": "keyword" + }, + "organization": { + "ignore_above": 1024, + "type": "keyword" + }, + "organizational_unit": { + "ignore_above": 1024, + "type": "keyword" + }, + "state_or_province": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "version_number": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "curve": { + "ignore_above": 1024, + "type": "keyword" + }, + "established": { + "type": "boolean" + }, + "next_protocol": { + "ignore_above": 1024, + "type": "keyword" + }, + "resumed": { + "type": "boolean" + }, + "server": { + "properties": { + "certificate": { + "ignore_above": 1024, + "type": "keyword" + }, + "certificate_chain": { + "ignore_above": 1024, + "type": "keyword" + }, + "hash": { + "properties": { + "md5": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha1": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha256": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "issuer": { + "ignore_above": 1024, + "type": "keyword" + }, + "ja3s": { + "ignore_above": 1024, + "type": "keyword" + }, + "not_after": { + "type": "date" + }, + "not_before": { + "type": "date" + }, + "subject": { + "ignore_above": 1024, + "type": "keyword" + }, + "x509": { + "properties": { + "alternative_names": { + "ignore_above": 1024, + "type": "keyword" + }, + "issuer": { + "properties": { + "common_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "country": { + "ignore_above": 1024, + "type": "keyword" + }, + "distinguished_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "locality": { + "ignore_above": 1024, + "type": "keyword" + }, + "organization": { + "ignore_above": 1024, + "type": "keyword" + }, + "organizational_unit": { + "ignore_above": 1024, + "type": "keyword" + }, + "state_or_province": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "not_after": { + "type": "date" + }, + "not_before": { + "type": "date" + }, + "public_key_algorithm": { + "ignore_above": 1024, + "type": "keyword" + }, + "public_key_curve": { + "ignore_above": 1024, + "type": "keyword" + }, + "public_key_exponent": { + "type": "long" + }, + "public_key_size": { + "type": "long" + }, + "serial_number": { + "ignore_above": 1024, + "type": "keyword" + }, + "signature_algorithm": { + "ignore_above": 1024, + "type": "keyword" + }, + "subject": { + "properties": { + "common_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "country": { + "ignore_above": 1024, + "type": "keyword" + }, + "distinguished_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "locality": { + "ignore_above": 1024, + "type": "keyword" + }, + "organization": { + "ignore_above": 1024, + "type": "keyword" + }, + "organizational_unit": { + "ignore_above": 1024, + "type": "keyword" + }, + "state_or_province": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "version_number": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + }, + "version_protocol": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "trace": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "transaction": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "url": { + "properties": { + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "extension": { + "ignore_above": 1024, + "type": "keyword" + }, + "fragment": { + "ignore_above": 1024, + "type": "keyword" + }, + "full": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "type": "wildcard" + }, + "original": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "type": "wildcard" + }, + "password": { + "ignore_above": 1024, + "type": "keyword" + }, + "path": { + "type": "wildcard" + }, + "port": { + "type": "long" + }, + "query": { + "ignore_above": 1024, + "type": "keyword" + }, + "registered_domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "scheme": { + "ignore_above": 1024, + "type": "keyword" + }, + "subdomain": { + "ignore_above": 1024, + "type": "keyword" + }, + "top_level_domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "username": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "user": { + "properties": { + "changes": { + "properties": { + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "email": { + "ignore_above": 1024, + "type": "keyword" + }, + "full_name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "group": { + "properties": { + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "roles": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "effective": { + "properties": { + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "email": { + "ignore_above": 1024, + "type": "keyword" + }, + "full_name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "group": { + "properties": { + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "roles": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "email": { + "ignore_above": 1024, + "type": "keyword" + }, + "full_name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "group": { + "properties": { + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "risk": { + "properties": { + "calculated_level": { + "ignore_above": 1024, + "type": "keyword" + }, + "calculated_score": { + "type": "float" + }, + "calculated_score_norm": { + "type": "float" + }, + "static_level": { + "ignore_above": 1024, + "type": "keyword" + }, + "static_score": { + "type": "float" + }, + "static_score_norm": { + "type": "float" + } + } + }, + "roles": { + "ignore_above": 1024, + "type": "keyword" + }, + "target": { + "properties": { + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "email": { + "ignore_above": 1024, + "type": "keyword" + }, + "full_name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "group": { + "properties": { + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "roles": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "user_agent": { + "properties": { + "device": { + "properties": { + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "original": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "os": { + "properties": { + "family": { + "ignore_above": 1024, + "type": "keyword" + }, + "full": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "kernel": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "platform": { + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "vulnerability": { + "properties": { + "category": { + "ignore_above": 1024, + "type": "keyword" + }, + "classification": { + "ignore_above": 1024, + "type": "keyword" + }, + "description": { + "fields": { + "text": { + "type": "match_only_text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "enumeration": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "reference": { + "ignore_above": 1024, + "type": "keyword" + }, + "report_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "scanner": { + "properties": { + "vendor": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "score": { + "properties": { + "base": { + "type": "float" + }, + "environmental": { + "type": "float" + }, + "temporal": { + "type": "float" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "severity": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "settings": { + "index": { + "auto_expand_replicas": "0-1", + "hidden": "true", + "mapping": { + "total_fields": { + "limit": "2500" + } + }, + "number_of_replicas": "0", + "number_of_shards": "1" + } + } + } +} diff --git a/x-pack/test/functional/es_archives/security_solution/ignore_fields/mappings.json b/x-pack/test/functional/es_archives/security_solution/ignore_fields/mappings.json index e2c8ca3c2bc89..3c2cbeac06cca 100644 --- a/x-pack/test/functional/es_archives/security_solution/ignore_fields/mappings.json +++ b/x-pack/test/functional/es_archives/security_solution/ignore_fields/mappings.json @@ -32,7 +32,6 @@ }, "settings": { "index": { - "refresh_interval": "1s", "number_of_replicas": "1", "number_of_shards": "1" } diff --git a/x-pack/test/functional/es_archives/security_solution/runtime/mappings.json b/x-pack/test/functional/es_archives/security_solution/runtime/mappings.json index fd3f30f2a2129..e0adb6cb55742 100644 --- a/x-pack/test/functional/es_archives/security_solution/runtime/mappings.json +++ b/x-pack/test/functional/es_archives/security_solution/runtime/mappings.json @@ -7027,7 +7027,6 @@ }, "settings": { "index": { - "refresh_interval": "1s", "number_of_replicas": "1", "number_of_shards": "1", "mapping": { diff --git a/x-pack/test/functional/es_archives/security_solution/runtime_conflicting_fields/mappings.json b/x-pack/test/functional/es_archives/security_solution/runtime_conflicting_fields/mappings.json index 2e34eae159a7f..ed15855be8e31 100644 --- a/x-pack/test/functional/es_archives/security_solution/runtime_conflicting_fields/mappings.json +++ b/x-pack/test/functional/es_archives/security_solution/runtime_conflicting_fields/mappings.json @@ -108,7 +108,6 @@ }, "settings": { "index": { - "refresh_interval": "1s", "number_of_replicas": "1", "number_of_shards": "1" } diff --git a/x-pack/test/functional/es_archives/security_solution/timestamp_in_seconds/mappings.json b/x-pack/test/functional/es_archives/security_solution/timestamp_in_seconds/mappings.json index fd8880fe0bc49..056d6467f510f 100644 --- a/x-pack/test/functional/es_archives/security_solution/timestamp_in_seconds/mappings.json +++ b/x-pack/test/functional/es_archives/security_solution/timestamp_in_seconds/mappings.json @@ -13,7 +13,6 @@ }, "settings": { "index": { - "refresh_interval": "1s", "number_of_replicas": "1", "number_of_shards": "1" } diff --git a/x-pack/test/functional/es_archives/security_solution/timestamp_override_5/mappings.json b/x-pack/test/functional/es_archives/security_solution/timestamp_override_5/mappings.json index a9735aaeca8ef..fd6f02966837c 100644 --- a/x-pack/test/functional/es_archives/security_solution/timestamp_override_5/mappings.json +++ b/x-pack/test/functional/es_archives/security_solution/timestamp_override_5/mappings.json @@ -30,7 +30,6 @@ }, "settings": { "index": { - "refresh_interval": "1s", "number_of_replicas": "1", "number_of_shards": "1" } diff --git a/x-pack/test/functional/es_archives/security_solution/timestamp_override_6/mappings.json b/x-pack/test/functional/es_archives/security_solution/timestamp_override_6/mappings.json index e3d8afd7a5b33..b1b35d6e1a23b 100644 --- a/x-pack/test/functional/es_archives/security_solution/timestamp_override_6/mappings.json +++ b/x-pack/test/functional/es_archives/security_solution/timestamp_override_6/mappings.json @@ -20,7 +20,6 @@ }, "settings": { "index": { - "refresh_interval": "1s", "number_of_replicas": "1", "number_of_shards": "1" } diff --git a/x-pack/test/functional/page_objects/lens_page.ts b/x-pack/test/functional/page_objects/lens_page.ts index 45b451721b2cd..927e8710017ee 100644 --- a/x-pack/test/functional/page_objects/lens_page.ts +++ b/x-pack/test/functional/page_objects/lens_page.ts @@ -1377,13 +1377,16 @@ export function LensPageProvider({ getService, getPageObjects }: FtrProviderCont * * @param title - title for the new lens. If left undefined, the panel will be created by value * @param redirectToOrigin - whether to redirect back to the dashboard after saving the panel + * @param ignoreTimeFilter - whether time range has to be changed */ async createAndAddLensFromDashboard({ title, redirectToOrigin, + ignoreTimeFilter, }: { title?: string; redirectToOrigin?: boolean; + ignoreTimeFilter?: boolean; }) { log.debug(`createAndAddLens${title}`); const inViewMode = await PageObjects.dashboard.getIsInViewMode(); @@ -1391,7 +1394,11 @@ export function LensPageProvider({ getService, getPageObjects }: FtrProviderCont await PageObjects.dashboard.switchToEditMode(); } await dashboardAddPanel.clickCreateNewLink(); - await this.goToTimeRange(); + + if (!ignoreTimeFilter) { + await this.goToTimeRange(); + } + await this.configureDimension({ dimension: 'lnsXY_yDimensionPanel > lns-empty-dimension', operation: 'average', diff --git a/x-pack/test/functional/services/cases/list.ts b/x-pack/test/functional/services/cases/list.ts index a83b11da78b78..ef3e61acf5213 100644 --- a/x-pack/test/functional/services/cases/list.ts +++ b/x-pack/test/functional/services/cases/list.ts @@ -19,6 +19,7 @@ export function CasesTableServiceProvider( const testSubjects = getService('testSubjects'); const find = getService('find'); const header = getPageObject('header'); + const browser = getService('browser'); const retry = getService('retry'); const config = getService('config'); @@ -392,5 +393,31 @@ export function CasesTableServiceProvider( return await titleElement.getVisibleText(); }, + + async hasColumn(columnName: string) { + const column = await find.allByCssSelector( + `th.euiTableHeaderCell span[title="${columnName}"]` + ); + return column.length !== 0; + }, + + async openColumnsPopover() { + await testSubjects.click('column-selection-popover-button'); + await testSubjects.existOrFail('column-selection-popover-drag-drop-context'); + }, + + async closeColumnsPopover() { + await testSubjects.click('column-selection-popover-button'); + }, + + async toggleColumnInPopover(columnId: string) { + await this.openColumnsPopover(); + + await testSubjects.existOrFail(`column-selection-switch-${columnId}`); + await testSubjects.click(`column-selection-switch-${columnId}`); + + // closes the popover + await browser.pressKeys(browser.keys.ESCAPE); + }, }; } diff --git a/x-pack/test/functional_cors/plugins/kibana_cors_test/server/index.ts b/x-pack/test/functional_cors/plugins/kibana_cors_test/server/index.ts index 6412a3892660d..59b1414effa5d 100644 --- a/x-pack/test/functional_cors/plugins/kibana_cors_test/server/index.ts +++ b/x-pack/test/functional_cors/plugins/kibana_cors_test/server/index.ts @@ -9,7 +9,8 @@ import type { PluginConfigDescriptor, PluginInitializerContext } from '@kbn/core import { CorsTestPlugin } from './plugin'; import { configSchema, ConfigSchema } from './config'; -export const plugin = (initContext: PluginInitializerContext) => new CorsTestPlugin(initContext); +export const plugin = async (initContext: PluginInitializerContext) => + new CorsTestPlugin(initContext); export const config: PluginConfigDescriptor = { schema: configSchema, diff --git a/x-pack/test/functional_embedded/plugins/iframe_embedded/server/index.ts b/x-pack/test/functional_embedded/plugins/iframe_embedded/server/index.ts index 19c53e78c4876..8501a5920f76a 100644 --- a/x-pack/test/functional_embedded/plugins/iframe_embedded/server/index.ts +++ b/x-pack/test/functional_embedded/plugins/iframe_embedded/server/index.ts @@ -8,5 +8,5 @@ import { PluginInitializerContext } from '@kbn/core/server'; import { IframeEmbeddedPlugin } from './plugin'; -export const plugin = (initContext: PluginInitializerContext) => +export const plugin = async (initContext: PluginInitializerContext) => new IframeEmbeddedPlugin(initContext); diff --git a/x-pack/test/functional_execution_context/plugins/alerts/server/index.ts b/x-pack/test/functional_execution_context/plugins/alerts/server/index.ts index dbd04e32e860b..0047ae70a993d 100644 --- a/x-pack/test/functional_execution_context/plugins/alerts/server/index.ts +++ b/x-pack/test/functional_execution_context/plugins/alerts/server/index.ts @@ -8,4 +8,4 @@ import './ensure_apm_started'; import { FixturePlugin } from './plugin'; -export const plugin = () => new FixturePlugin(); +export const plugin = async () => new FixturePlugin(); diff --git a/x-pack/test/functional_execution_context/tests/browser.ts b/x-pack/test/functional_execution_context/tests/browser.ts index 1696b7ef3c312..f7d265316decb 100644 --- a/x-pack/test/functional_execution_context/tests/browser.ts +++ b/x-pack/test/functional_execution_context/tests/browser.ts @@ -12,8 +12,28 @@ import { assertLogContains, isExecutionContextLog, readLogFile } from '../test_u export default function ({ getService, getPageObjects }: FtrProviderContext) { const PageObjects = getPageObjects(['common', 'dashboard', 'header', 'home', 'timePicker']); - // Failing: See https://github.com/elastic/kibana/issues/166007 - describe.skip('Browser apps', () => { + describe('Browser apps', () => { + let logs: Ecs[]; + const retry = getService('retry'); + + const logContains = async ({ + predicate, + description, + }: { + predicate: (record: Ecs) => boolean; + description: string; + }) => { + return retry.try(async () => { + try { + await assertLogContains({ logs, predicate, description }); + } catch (err) { + // if we did not find our predicate in the logs, wait a bit and parse them again + await new Promise((resolve) => setTimeout(resolve, 10000)); + logs = await readLogFile(); + throw err; + } + }); + }; before(async () => { await PageObjects.common.navigateToUrl('home', '/tutorial_directory/sampleData', { useActualUrl: true, @@ -31,8 +51,6 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { }); describe('discover app', () => { - let logs: Ecs[]; - before(async () => { await PageObjects.common.navigateToApp('discover'); await PageObjects.timePicker.setCommonlyUsedTime('Last_7 days'); @@ -53,16 +71,15 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { describe('propagates context for Discover', () => { it('propagates to Elasticsearch via "x-opaque-id" header', async () => { - await assertLogContains({ + await logContains({ description: 'execution context propagates to Elasticsearch via "x-opaque-id" header', predicate: (record) => Boolean(record.http?.request?.id?.includes('kibana:application:discover')), - logs, }); }); it('propagates to Kibana logs (fetch documents)', async () => { - await assertLogContains({ + await logContains({ description: 'execution context propagates to Kibana logs (fetch documents)', predicate: checkExecutionContextEntry({ type: 'application', @@ -77,12 +94,11 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { description: 'fetch documents', }, }), - logs, }); }); it('propagates to Kibana logs (fetch chart data and total hits)', async () => { - await assertLogContains({ + await logContains({ description: 'execution context propagates to Kibana logs (fetch chart data and total hits)', predicate: checkExecutionContextEntry({ @@ -105,15 +121,12 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { }, }, }), - logs, }); }); }); }); describe('dashboard app', () => { - let logs: Ecs[]; - before(async () => { await PageObjects.common.navigateToApp('dashboard'); await PageObjects.dashboard.loadSavedDashboard('[Flights] Global Flight Dashboard'); @@ -170,17 +183,16 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { describe('propagates context for Lens visualizations', () => { describe('lnsXY', () => { it('propagates to Elasticsearch via "x-opaque-id" header', async () => { - await assertLogContains({ + await logContains({ description: 'execution context propagates to Elasticsearch via "x-opaque-id" header', predicate: checkHttpRequestId( 'dashboard:dashboards:7adfa750-4c81-11e8-b3d7-01146121b73d;lens:lnsXY:086ac2e9-dd16-4b45-92b8-1e43ff7e3f65' ), - logs, }); }); it('propagates to Kibana logs', async () => { - await assertLogContains({ + await logContains({ description: 'execution context propagates to Kibana logs', predicate: checkExecutionContextEntry({ type: 'application', @@ -202,24 +214,22 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { }, }, }), - logs, }); }); }); - describe.skip('lnsMetric', () => { + describe('lnsMetric', () => { it('propagates to Elasticsearch via "x-opaque-id" header', async () => { - await assertLogContains({ + await logContains({ description: 'execution context propagates to Elasticsearch via "x-opaque-id" header', predicate: checkHttpRequestId( - 'dashboard:dashboards:7adfa750-4c81-11e8-b3d7-01146121b73d;lens:lnsLegacyMetric:b766e3b8-4544-46ed-99e6-9ecc4847e2a2' + 'dashboard:dashboards:7adfa750-4c81-11e8-b3d7-01146121b73d;lens:lnsMetric:b766e3b8-4544-46ed-99e6-9ecc4847e2a2' ), - logs, }); }); it('propagates to Kibana logs', async () => { - await assertLogContains({ + await logContains({ description: 'execution context propagates to Kibana logs', predicate: checkExecutionContextEntry({ name: 'dashboards', @@ -234,31 +244,29 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { description: '[Flights] Global Flight Dashboard', child: { type: 'lens', - name: 'lnsLegacyMetric', + name: 'lnsMetric', id: 'b766e3b8-4544-46ed-99e6-9ecc4847e2a2', description: '', url: '/app/lens#/edit_by_value', }, }, }), - logs, }); }); }); describe('lnsDatatable', () => { it('propagates to Elasticsearch via "x-opaque-id" header', async () => { - await assertLogContains({ + await logContains({ description: 'execution context propagates to Elasticsearch via "x-opaque-id" header', predicate: checkHttpRequestId( 'dashboard:dashboards:7adfa750-4c81-11e8-b3d7-01146121b73d;lens:lnsDatatable:fb86b32f-fb7a-45cf-9511-f366fef51bbd' ), - logs, }); }); it('propagates to Kibana logs', async () => { - await assertLogContains({ + await logContains({ description: 'execution context propagates to Kibana logs', predicate: checkExecutionContextEntry({ name: 'dashboards', @@ -280,24 +288,22 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { }, }, }), - logs, }); }); }); describe('lnsPie', () => { it('propagates to Elasticsearch via "x-opaque-id" header', async () => { - await assertLogContains({ + await logContains({ description: 'execution context propagates to Elasticsearch via "x-opaque-id" header', predicate: checkHttpRequestId( 'dashboard:dashboards:7adfa750-4c81-11e8-b3d7-01146121b73d;lens:lnsPie:5d53db36-2d5a-4adc-af7b-cec4c1a294e0' ), - logs, }); }); it('propagates to Kibana logs', async () => { - await assertLogContains({ + await logContains({ description: 'execution context propagates to Kibana logs', predicate: checkExecutionContextEntry({ name: 'dashboards', @@ -319,7 +325,6 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { }, }, }), - logs, }); }); }); @@ -327,17 +332,16 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { describe('propagates context for built-in Discover', () => { it('propagates to Elasticsearch via "x-opaque-id" header', async () => { - await assertLogContains({ + await logContains({ description: 'execution context propagates to Elasticsearch via "x-opaque-id" header', predicate: checkHttpRequestId( 'dashboard:dashboards:7adfa750-4c81-11e8-b3d7-01146121b73d;search:discover:571aaf70-4c88-11e8-b3d7-01146121b73d' ), - logs, }); }); it('propagates to Kibana logs', async () => { - await assertLogContains({ + await logContains({ description: 'execution context propagates to Kibana logs', predicate: checkExecutionContextEntry({ type: 'application', @@ -359,22 +363,20 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { }, }, }), - logs, }); }); }); describe.skip('propagates context for TSVB visualizations', () => { it('propagates to Elasticsearch via "x-opaque-id" header', async () => { - await assertLogContains({ + await logContains({ description: 'execution context propagates to Elasticsearch via "x-opaque-id" header', predicate: checkHttpRequestId('agg_based:metrics:bcb63b50-4c89-11e8-b3d7-01146121b73d'), - logs, }); }); it('propagates to Kibana logs', async () => { - await assertLogContains({ + await logContains({ description: 'execution context propagates to Kibana logs', predicate: checkExecutionContextEntry({ name: 'dashboards', @@ -390,24 +392,23 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { url: '/app/visualize#/edit/bcb63b50-4c89-11e8-b3d7-01146121b73d', }, }), - logs, }); }); }); describe('propagates context for Vega visualizations', () => { + // CHECKPOINT this is the test that failed and caused the global .skip() it('propagates to Elasticsearch via "x-opaque-id" header', async () => { - await assertLogContains({ + await logContains({ description: 'execution context propagates to Elasticsearch via "x-opaque-id" header', predicate: checkHttpRequestId( 'dashboard:dashboards:7adfa750-4c81-11e8-b3d7-01146121b73d;agg_based:vega:ed78a660-53a0-11e8-acbd-0be0ad9d822b' ), - logs, }); }); it('propagates to Kibana logs', async () => { - await assertLogContains({ + await logContains({ description: 'execution context propagates to Kibana logs', predicate: checkExecutionContextEntry({ name: 'dashboards', @@ -429,24 +430,22 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { }, }, }), - logs, }); }); }); describe.skip('propagates context for Tag Cloud visualization', () => { it('propagates to Elasticsearch via "x-opaque-id" header', async () => { - await assertLogContains({ + await logContains({ description: 'execution context propagates to Elasticsearch via "x-opaque-id" header', predicate: checkHttpRequestId( 'dashboard:dashboards:7adfa750-4c81-11e8-b3d7-01146121b73d;agg_based:tagcloud:293b5a30-4c8f-11e8-b3d7-01146121b73d' ), - logs, }); }); it('propagates to Kibana logs', async () => { - await assertLogContains({ + await logContains({ description: 'execution context propagates to Kibana logs', predicate: checkExecutionContextEntry({ name: 'dashboards', @@ -468,24 +467,22 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { }, }, }), - logs, }); }); }); describe.skip('propagates context for Vertical bar visualization', () => { it('propagates to Elasticsearch via "x-opaque-id" header', async () => { - await assertLogContains({ + await logContains({ description: 'execution context propagates to Elasticsearch via "x-opaque-id" header', predicate: checkHttpRequestId( 'dashboard:dashboards:7adfa750-4c81-11e8-b3d7-01146121b73d;agg_based:histogram:9886b410-4c8b-11e8-b3d7-01146121b73d' ), - logs, }); }); it('propagates to Kibana logs', async () => { - await assertLogContains({ + await logContains({ description: 'execution context propagates to Kibana logs', predicate: checkExecutionContextEntry({ type: 'application', @@ -507,7 +504,6 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { }, }, }), - logs, }); }); }); diff --git a/x-pack/test/functional_with_es_ssl/apps/cases/group2/list_view.ts b/x-pack/test/functional_with_es_ssl/apps/cases/group2/list_view.ts index 51a37c1eaccd9..c1d2b2a9d7c0c 100644 --- a/x-pack/test/functional_with_es_ssl/apps/cases/group2/list_view.ts +++ b/x-pack/test/functional_with_es_ssl/apps/cases/group2/list_view.ts @@ -656,5 +656,81 @@ export default ({ getPageObject, getService }: FtrProviderContext) => { }); }); }); + + describe('Column Selection', () => { + afterEach(async () => { + await toasts.dismissAllToastsWithChecks(); + }); + + before(async () => { + await cases.api.createNthRandomCases(1); + await header.waitUntilLoadingHasFinished(); + await cases.casesTable.waitForCasesToBeListed(); + }); + + after(async () => { + await cases.api.deleteAllCases(); + await cases.casesTable.waitForCasesToBeDeleted(); + await browser.clearLocalStorage(); + }); + + it('column selection popover button exists', async () => { + await testSubjects.existOrFail('column-selection-popover-button'); + }); + + it('selecting a column works correctly', async () => { + expect(await cases.casesTable.hasColumn('Closed on')).to.be(false); + + await cases.casesTable.toggleColumnInPopover('closedAt'); + + expect(await cases.casesTable.hasColumn('Closed on')).to.be(true); + }); + + it('deselecting columns works correctly', async () => { + expect(await cases.casesTable.hasColumn('Name')).to.be(true); + + await cases.casesTable.toggleColumnInPopover('title'); + + expect(await cases.casesTable.hasColumn('Name')).to.be(false); + }); + + it('"Hide All" columns works correctly', async () => { + await cases.casesTable.openColumnsPopover(); + + await testSubjects.click('column-selection-popover-hide-all-button'); + + await cases.casesTable.closeColumnsPopover(); + + expect(await cases.casesTable.hasColumn('Name')).to.be(false); + expect(await cases.casesTable.hasColumn('Assignees')).to.be(false); + expect(await cases.casesTable.hasColumn('Tags')).to.be(false); + expect(await cases.casesTable.hasColumn('Category')).to.be(false); + }); + + it('"Show All" columns works correctly', async () => { + await cases.casesTable.openColumnsPopover(); + + await testSubjects.click('column-selection-popover-show-all-button'); + + await cases.casesTable.closeColumnsPopover(); + + expect(await cases.casesTable.hasColumn('Name')).to.be(true); + expect(await cases.casesTable.hasColumn('Assignees')).to.be(true); + expect(await cases.casesTable.hasColumn('Tags')).to.be(true); + expect(await cases.casesTable.hasColumn('Category')).to.be(true); + expect(await cases.casesTable.hasColumn('Closed on')).to.be(true); + }); + + it('search and toggle column works correctly', async () => { + await cases.casesTable.openColumnsPopover(); + + const input = await testSubjects.find('column-selection-popover-search'); + await input.type('name'); + + await testSubjects.existOrFail('column-selection-switch-title'); + await testSubjects.missingOrFail('column-selection-switch-closedAt'); + await testSubjects.missingOrFail('column-selection-switch-category'); + }); + }); }); }; diff --git a/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/alert_create_flyout.ts b/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/alert_create_flyout.ts index cdf9cc87684ad..3cceb01b54998 100644 --- a/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/alert_create_flyout.ts +++ b/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/alert_create_flyout.ts @@ -155,6 +155,19 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { await testSubjects.click('notifyWhenSelect'); await testSubjects.click('onThrottleInterval'); await testSubjects.setValue('throttleInput', '10'); + + // Alerts search bar (conditional actions) + await testSubjects.click('alertsFilterQueryToggle'); + + await pageObjects.header.waitUntilLoadingHasFinished(); + await testSubjects.click('addFilter'); + await testSubjects.click('filterFieldSuggestionList'); + await comboBox.set('filterFieldSuggestionList', '_id'); + await comboBox.set('filterOperatorList', 'is not'); + await testSubjects.setValue('filterParams', 'fake-rule-id'); + await testSubjects.click('saveFilter'); + await testSubjects.setValue('queryInput', '_id: *'); + const messageTextArea = await find.byCssSelector('[data-test-subj="messageTextArea"]'); expect(await messageTextArea.getAttribute('value')).to.eql( `Rule '{{rule.name}}' is active for group '{{context.group}}': diff --git a/x-pack/test/functional_with_es_ssl/plugins/alerts/server/index.ts b/x-pack/test/functional_with_es_ssl/plugins/alerts/server/index.ts index b7c2aea144b5b..131cc04b22bf6 100644 --- a/x-pack/test/functional_with_es_ssl/plugins/alerts/server/index.ts +++ b/x-pack/test/functional_with_es_ssl/plugins/alerts/server/index.ts @@ -8,4 +8,4 @@ import { PluginInitializer } from '@kbn/core/server'; import { AlertingFixturePlugin } from './plugin'; -export const plugin: PluginInitializer = () => new AlertingFixturePlugin(); +export const plugin: PluginInitializer = async () => new AlertingFixturePlugin(); diff --git a/x-pack/test/functional_with_es_ssl/plugins/cases/server/index.ts b/x-pack/test/functional_with_es_ssl/plugins/cases/server/index.ts index df682115bd93a..ef145ab0ee92f 100644 --- a/x-pack/test/functional_with_es_ssl/plugins/cases/server/index.ts +++ b/x-pack/test/functional_with_es_ssl/plugins/cases/server/index.ts @@ -8,4 +8,4 @@ import { PluginInitializer } from '@kbn/core/server'; import { CasesFixturePlugin } from './plugin'; -export const plugin: PluginInitializer = () => new CasesFixturePlugin(); +export const plugin: PluginInitializer = async () => new CasesFixturePlugin(); diff --git a/x-pack/test/plugin_api_integration/plugins/elasticsearch_client/server/index.ts b/x-pack/test/plugin_api_integration/plugins/elasticsearch_client/server/index.ts index c101370938471..e95ccfe3eaa12 100644 --- a/x-pack/test/plugin_api_integration/plugins/elasticsearch_client/server/index.ts +++ b/x-pack/test/plugin_api_integration/plugins/elasticsearch_client/server/index.ts @@ -7,4 +7,4 @@ import { ElasticsearchClientXPack } from './plugin'; -export const plugin = () => new ElasticsearchClientXPack(); +export const plugin = async () => new ElasticsearchClientXPack(); diff --git a/x-pack/test/plugin_api_integration/plugins/event_log/server/index.ts b/x-pack/test/plugin_api_integration/plugins/event_log/server/index.ts index eb8bfa1b80cff..24c0958a58488 100644 --- a/x-pack/test/plugin_api_integration/plugins/event_log/server/index.ts +++ b/x-pack/test/plugin_api_integration/plugins/event_log/server/index.ts @@ -8,5 +8,5 @@ import { PluginInitializerContext } from '@kbn/core/server'; import { EventLogFixturePlugin } from './plugin'; -export const plugin = (initContext: PluginInitializerContext) => +export const plugin = async (initContext: PluginInitializerContext) => new EventLogFixturePlugin(initContext); diff --git a/x-pack/test/plugin_api_integration/plugins/feature_usage_test/server/index.ts b/x-pack/test/plugin_api_integration/plugins/feature_usage_test/server/index.ts index b649fbc808272..6d0e1606f0044 100644 --- a/x-pack/test/plugin_api_integration/plugins/feature_usage_test/server/index.ts +++ b/x-pack/test/plugin_api_integration/plugins/feature_usage_test/server/index.ts @@ -15,4 +15,4 @@ import { export const plugin: PluginInitializer< FeatureUsageTestPluginSetup, FeatureUsageTestPluginStart -> = () => new FeatureUsageTestPlugin(); +> = async () => new FeatureUsageTestPlugin(); diff --git a/x-pack/test/plugin_api_integration/plugins/sample_task_plugin/server/index.ts b/x-pack/test/plugin_api_integration/plugins/sample_task_plugin/server/index.ts index bed262d69ea18..9ef27eac56335 100644 --- a/x-pack/test/plugin_api_integration/plugins/sample_task_plugin/server/index.ts +++ b/x-pack/test/plugin_api_integration/plugins/sample_task_plugin/server/index.ts @@ -7,4 +7,4 @@ import { SampleTaskManagerFixturePlugin } from './plugin'; -export const plugin = () => new SampleTaskManagerFixturePlugin(); +export const plugin = async () => new SampleTaskManagerFixturePlugin(); diff --git a/x-pack/test/plugin_api_perf/plugins/task_manager_performance/server/index.ts b/x-pack/test/plugin_api_perf/plugins/task_manager_performance/server/index.ts index bed262d69ea18..9ef27eac56335 100644 --- a/x-pack/test/plugin_api_perf/plugins/task_manager_performance/server/index.ts +++ b/x-pack/test/plugin_api_perf/plugins/task_manager_performance/server/index.ts @@ -7,4 +7,4 @@ import { SampleTaskManagerFixturePlugin } from './plugin'; -export const plugin = () => new SampleTaskManagerFixturePlugin(); +export const plugin = async () => new SampleTaskManagerFixturePlugin(); diff --git a/x-pack/test/reporting_api_integration/reporting_and_security/csv_v2.ts b/x-pack/test/reporting_api_integration/reporting_and_security/csv_v2.ts index 04ff7adc357e3..5b70c5db2fd8a 100644 --- a/x-pack/test/reporting_api_integration/reporting_and_security/csv_v2.ts +++ b/x-pack/test/reporting_api_integration/reporting_and_security/csv_v2.ts @@ -5,14 +5,13 @@ * 2.0. */ -import { DISCOVER_APP_LOCATOR } from '@kbn/discover-plugin/common'; import expect from '@kbn/expect'; -import type { - JobParamsCsvFromSavedObject, - ReportApiJSON, -} from '@kbn/reporting-plugin/common/types'; -import rison from '@kbn/rison'; import request from 'supertest'; + +import { DISCOVER_APP_LOCATOR } from '@kbn/discover-plugin/common'; +import type { JobParamsCsvFromSavedObject } from '@kbn/reporting-export-types-csv-common'; +import type { ReportApiJSON } from '@kbn/reporting-common/types'; +import rison from '@kbn/rison'; import { FtrProviderContext } from '../ftr_provider_context'; const LOGSTASH_DATA_ARCHIVE = 'test/functional/fixtures/es_archiver/logstash_functional'; diff --git a/x-pack/test/reporting_api_integration/reporting_and_security/download_csv_dashboard.ts b/x-pack/test/reporting_api_integration/reporting_and_security/download_csv_dashboard.ts index f71efb61aeb2c..bd389cd49ea87 100644 --- a/x-pack/test/reporting_api_integration/reporting_and_security/download_csv_dashboard.ts +++ b/x-pack/test/reporting_api_integration/reporting_and_security/download_csv_dashboard.ts @@ -6,8 +6,8 @@ */ import expect from '@kbn/expect'; +import type { JobParamsDownloadCSV } from '@kbn/reporting-export-types-csv-common'; import supertest from 'supertest'; -import { JobParamsDownloadCSV } from '@kbn/reporting-plugin/server/export_types/csv_searchsource_immediate/types'; import { FtrProviderContext } from '../ftr_provider_context'; const getMockJobParams = (obj: object) => { diff --git a/x-pack/test/reporting_api_integration/reporting_and_security/error_codes.ts b/x-pack/test/reporting_api_integration/reporting_and_security/error_codes.ts index 0d83da710ba23..1f417a3d526c2 100644 --- a/x-pack/test/reporting_api_integration/reporting_and_security/error_codes.ts +++ b/x-pack/test/reporting_api_integration/reporting_and_security/error_codes.ts @@ -7,7 +7,7 @@ import expect from '@kbn/expect'; import { INTERNAL_ROUTES } from '@kbn/reporting-plugin/common/constants/routes'; -import { ReportApiJSON } from '@kbn/reporting-plugin/common/types'; +import { ReportApiJSON } from '@kbn/reporting-common/types'; import { FtrProviderContext } from '../ftr_provider_context'; // eslint-disable-next-line import/no-default-export diff --git a/x-pack/test/reporting_api_integration/reporting_and_security/generate_csv_discover.ts b/x-pack/test/reporting_api_integration/reporting_and_security/generate_csv_discover.ts index d7f9d772f826d..951fdf8ec5772 100644 --- a/x-pack/test/reporting_api_integration/reporting_and_security/generate_csv_discover.ts +++ b/x-pack/test/reporting_api_integration/reporting_and_security/generate_csv_discover.ts @@ -7,7 +7,7 @@ import expect from '@kbn/expect'; import { SerializedSearchSourceFields } from '@kbn/data-plugin/common'; -import { ReportApiJSON } from '@kbn/reporting-plugin/common/types'; +import { ReportApiJSON } from '@kbn/reporting-common/types'; import { FtrProviderContext } from '../ftr_provider_context'; // eslint-disable-next-line import/no-default-export diff --git a/x-pack/test/reporting_api_integration/reporting_and_security/ilm_migration_apis.ts b/x-pack/test/reporting_api_integration/reporting_and_security/ilm_migration_apis.ts index 6f71974364942..172d415ff2695 100644 --- a/x-pack/test/reporting_api_integration/reporting_and_security/ilm_migration_apis.ts +++ b/x-pack/test/reporting_api_integration/reporting_and_security/ilm_migration_apis.ts @@ -6,7 +6,7 @@ */ import expect from '@kbn/expect'; -import { ILM_POLICY_NAME } from '@kbn/reporting-plugin/common/constants'; +import { ILM_POLICY_NAME } from '@kbn/reporting-common/constants'; import { INTERNAL_ROUTES } from '@kbn/reporting-plugin/common/constants/routes'; import { FtrProviderContext } from '../ftr_provider_context'; diff --git a/x-pack/test/reporting_api_integration/reporting_without_security/job_apis_csv.ts b/x-pack/test/reporting_api_integration/reporting_without_security/job_apis_csv.ts index 30f58524b46f8..921ad4ef6a915 100644 --- a/x-pack/test/reporting_api_integration/reporting_without_security/job_apis_csv.ts +++ b/x-pack/test/reporting_api_integration/reporting_without_security/job_apis_csv.ts @@ -7,7 +7,7 @@ import expect from '@kbn/expect'; import { INTERNAL_ROUTES } from '@kbn/reporting-plugin/common/constants/routes'; -import { ReportApiJSON } from '@kbn/reporting-plugin/common/types'; +import { ReportApiJSON } from '@kbn/reporting-common/types'; import { pick } from 'lodash'; import { FtrProviderContext } from '../ftr_provider_context'; diff --git a/x-pack/test/reporting_api_integration/services/scenarios.ts b/x-pack/test/reporting_api_integration/services/scenarios.ts index dee9c08231466..98471d94cc4e6 100644 --- a/x-pack/test/reporting_api_integration/services/scenarios.ts +++ b/x-pack/test/reporting_api_integration/services/scenarios.ts @@ -6,10 +6,9 @@ */ import { INTERNAL_ROUTES } from '@kbn/reporting-plugin/common/constants/routes'; -import { JobParamsCSV } from '@kbn/reporting-plugin/server/export_types/csv_searchsource/types'; -import { JobParamsDownloadCSV } from '@kbn/reporting-plugin/server/export_types/csv_searchsource_immediate/types'; -import { JobParamsPNGV2 } from '@kbn/reporting-plugin/server/export_types/png_v2/types'; -import { JobParamsPDFDeprecated } from '@kbn/reporting-plugin/server/export_types/printable_pdf/types'; +import type { JobParamsPDFDeprecated } from '@kbn/reporting-export-types-pdf-common'; +import type { JobParamsPNGV2 } from '@kbn/reporting-export-types-png-common'; +import type { JobParamsCSV, JobParamsDownloadCSV } from '@kbn/reporting-export-types-csv-common'; import rison from '@kbn/rison'; import { FtrProviderContext } from '../ftr_provider_context'; diff --git a/x-pack/test/saved_object_api_integration/common/plugins/saved_object_test_plugin/server/index.ts b/x-pack/test/saved_object_api_integration/common/plugins/saved_object_test_plugin/server/index.ts index 1db5fe493b35b..e30ef09b951ee 100644 --- a/x-pack/test/saved_object_api_integration/common/plugins/saved_object_test_plugin/server/index.ts +++ b/x-pack/test/saved_object_api_integration/common/plugins/saved_object_test_plugin/server/index.ts @@ -7,6 +7,6 @@ import { Plugin } from './plugin'; -export function plugin() { +export async function plugin() { return new Plugin(); } diff --git a/x-pack/test/security_api_integration/plugins/audit_log/server/index.ts b/x-pack/test/security_api_integration/plugins/audit_log/server/index.ts index 7328c41ac6d1a..342396a8cde4b 100644 --- a/x-pack/test/security_api_integration/plugins/audit_log/server/index.ts +++ b/x-pack/test/security_api_integration/plugins/audit_log/server/index.ts @@ -7,4 +7,4 @@ import { AuditTrailTestPlugin } from './plugin'; -export const plugin = () => new AuditTrailTestPlugin(); +export const plugin = async () => new AuditTrailTestPlugin(); diff --git a/x-pack/test/security_api_integration/plugins/oidc_provider/server/index.ts b/x-pack/test/security_api_integration/plugins/oidc_provider/server/index.ts index b5a6123de4398..82e460a6a4c27 100644 --- a/x-pack/test/security_api_integration/plugins/oidc_provider/server/index.ts +++ b/x-pack/test/security_api_integration/plugins/oidc_provider/server/index.ts @@ -8,7 +8,7 @@ import type { PluginInitializer, Plugin } from '@kbn/core/server'; import { initRoutes } from './init_routes'; -export const plugin: PluginInitializer = (): Plugin => ({ +export const plugin: PluginInitializer = async (): Promise => ({ setup: (core) => initRoutes(core.http.createRouter()), start: () => {}, stop: () => {}, diff --git a/x-pack/test/security_api_integration/plugins/saml_provider/server/index.ts b/x-pack/test/security_api_integration/plugins/saml_provider/server/index.ts index 5558cceea2572..9a5efa5fa6861 100644 --- a/x-pack/test/security_api_integration/plugins/saml_provider/server/index.ts +++ b/x-pack/test/security_api_integration/plugins/saml_provider/server/index.ts @@ -8,7 +8,7 @@ import type { PluginInitializer, Plugin } from '@kbn/core/server'; import { initRoutes } from './init_routes'; -export const plugin: PluginInitializer = (): Plugin => ({ +export const plugin: PluginInitializer = async (): Promise => ({ setup: (core) => initRoutes(core), start: () => {}, stop: () => {}, diff --git a/x-pack/test/security_api_integration/plugins/user_profiles_consumer/server/index.ts b/x-pack/test/security_api_integration/plugins/user_profiles_consumer/server/index.ts index 9467c7b4358b4..7cd8187558a88 100644 --- a/x-pack/test/security_api_integration/plugins/user_profiles_consumer/server/index.ts +++ b/x-pack/test/security_api_integration/plugins/user_profiles_consumer/server/index.ts @@ -26,11 +26,8 @@ export interface PluginStartDependencies { spaces: SpacesPluginStart; } -export const plugin: PluginInitializer = (): Plugin< - void, - void, - PluginSetupDependencies, - PluginStartDependencies +export const plugin: PluginInitializer = async (): Promise< + Plugin > => ({ setup: (core: CoreSetup) => initRoutes(core), start: () => {}, diff --git a/x-pack/test/security_functional/plugins/test_endpoints/server/index.ts b/x-pack/test/security_functional/plugins/test_endpoints/server/index.ts index 33ce96a3cfffa..38ad79b213218 100644 --- a/x-pack/test/security_functional/plugins/test_endpoints/server/index.ts +++ b/x-pack/test/security_functional/plugins/test_endpoints/server/index.ts @@ -20,9 +20,9 @@ export interface PluginStartDependencies { taskManager: TaskManagerStartContract; } -export const plugin: PluginInitializer = ( +export const plugin: PluginInitializer = async ( initializerContext -): Plugin => ({ +): Promise> => ({ setup: (core: CoreSetup) => initRoutes(initializerContext, core), start: () => {}, stop: () => {}, diff --git a/x-pack/test/security_solution_api_integration/config/serverless/config.base.ts b/x-pack/test/security_solution_api_integration/config/serverless/config.base.ts index 6238282722cfc..374538e593efa 100644 --- a/x-pack/test/security_solution_api_integration/config/serverless/config.base.ts +++ b/x-pack/test/security_solution_api_integration/config/serverless/config.base.ts @@ -11,15 +11,18 @@ export interface CreateTestConfigOptions { kbnTestServerArgs?: string[]; kbnTestServerEnv?: Record; } +import { services } from '../../../../test_serverless/api_integration/services'; export function createTestConfig(options: CreateTestConfigOptions) { return async ({ readConfigFile }: FtrConfigProviderContext) => { const svlSharedConfig = await readConfigFile( require.resolve('../../../../test_serverless/shared/config.base.ts') ); - return { ...svlSharedConfig.getAll(), + services: { + ...services, + }, kbnTestServer: { ...svlSharedConfig.get('kbnTestServer'), serverArgs: [ diff --git a/x-pack/test/security_solution_api_integration/es_archive/serverless/filebeat/threat_intel/data.json b/x-pack/test/security_solution_api_integration/es_archive/serverless/filebeat/threat_intel/data.json new file mode 100644 index 0000000000000..80ccf200301c7 --- /dev/null +++ b/x-pack/test/security_solution_api_integration/es_archive/serverless/filebeat/threat_intel/data.json @@ -0,0 +1,418 @@ +{ + "type": "doc", + "value": { + "id": "978783", + "index": "filebeat-8.0.0-2021.01.26-000001", + "source": { + "@timestamp": "2021-01-26T11:09:05.529Z", + "agent": { + "ephemeral_id": "b7b56c3e-1f27-4c69-96f4-aa9ca47888d0", + "id": "69acb5f0-1e79-4cfe-a4dc-e0dbf229ff51", + "name": "MacBook-Pro-de-Gloria.local", + "type": "filebeat", + "version": "8.0.0" + }, + "ecs": { + "version": "1.6.0" + }, + "event": { + "category": "threat", + "created": "2021-01-26T11:09:05.529Z", + "dataset": "ti_abusech.malware", + "ingested": "2021-01-26T11:09:06.595350Z", + "kind": "enrichment", + "module": "threatintel", + "reference": "https://urlhaus.abuse.ch/url/978783/", + "type": "indicator" + }, + "fileset": { + "name": "abuseurl" + }, + "input": { + "type": "httpjson" + }, + "service": { + "type": "threatintel" + }, + "tags": [ + "threatintel-abuseurls", + "forwarded" + ], + "threat": { + "indicator": { + "description": "domain should match the auditbeat hosts' data's source.ip", + "domain": "159.89.119.67", + "first_seen": "2021-01-26T11:09:04.000Z", + "provider": "geenensp", + "type": "url", + "url": { + "full": "http://159.89.119.67:59600/bin.sh", + "scheme": "http" + } + } + }, + "threatintel": { + "abuseurl": { + "blacklists": { + "spamhaus_dbl": "not listed", + "surbl": "not listed" + }, + "larted": false, + "tags": null, + "threat": "malware_download", + "url_status": "online" + } + } + } + } +} + +{ + "type": "doc", + "value": { + "id": "978784", + "index": "filebeat-8.0.0-2021.01.26-000001", + "source": { + "@timestamp": "2021-01-26T11:09:05.529Z", + "agent": { + "ephemeral_id": "b7b56c3e-1f27-4c69-96f4-aa9ca47888d0", + "id": "69acb5f0-1e79-4cfe-a4dc-e0dbf229ff51", + "name": "MacBook-Pro-de-Gloria.local", + "type": "filebeat", + "version": "8.0.0" + }, + "ecs": { + "version": "1.6.0" + }, + "event": { + "category": "threat", + "created": "2021-01-26T11:09:05.529Z", + "dataset": "ti_abusech.malware", + "ingested": "2021-01-26T11:09:06.616763Z", + "kind": "enrichment", + "module": "threatintel", + "reference": "https://urlhaus.abuse.ch/url/978782/", + "type": "indicator" + }, + "fileset": { + "name": "abuseurl" + }, + "input": { + "type": "httpjson" + }, + "service": { + "type": "threatintel" + }, + "tags": [ + "threatintel-abuseurls", + "forwarded" + ], + "threat": { + "indicator": { + "description": "this should not match the auditbeat hosts data", + "ip": "125.46.136.106", + "first_seen": "2021-01-26T11:06:03.000Z", + "provider": "geenensp", + "type": "ip" + } + }, + "threatintel": { + "abuseurl": { + "blacklists": { + "spamhaus_dbl": "not listed", + "surbl": "not listed" + }, + "larted": true, + "tags": [ + "32-bit", + "elf", + "mips" + ], + "threat": "malware_download", + "url_status": "online" + } + } + } + } +} + +{ + "type": "doc", + "value": { + "id": "978785", + "index": "filebeat-8.0.0-2021.01.26-000001", + "source": { + "@timestamp": "2021-01-26T11:09:05.529Z", + "agent": { + "ephemeral_id": "b7b56c3e-1f27-4c69-96f4-aa9ca47888d0", + "id": "69acb5f0-1e79-4cfe-a4dc-e0dbf229ff51", + "name": "MacBook-Pro-de-Gloria.local", + "type": "filebeat", + "version": "8.0.0" + }, + "ecs": { + "version": "1.6.0" + }, + "event": { + "category": "threat", + "created": "2021-01-26T11:09:05.529Z", + "dataset": "ti_abusech.malware", + "ingested": "2021-01-26T11:09:06.616763Z", + "kind": "enrichment", + "module": "threatintel", + "reference": "https://urlhaus.abuse.ch/url/978782/", + "type": "indicator" + }, + "fileset": { + "name": "abuseurl" + }, + "input": { + "type": "httpjson" + }, + "service": { + "type": "threatintel" + }, + "tags": [ + "threatintel-abuseurls", + "forwarded" + ], + "threat": { + "indicator": { + "description": "this should match auditbeat/hosts on both port and ip", + "ip": "45.115.45.3", + "port": 57324, + "first_seen": "2021-01-26T11:06:03.000Z", + "provider": "geenensp", + "type": "url" + } + }, + "threatintel": { + "abuseurl": { + "blacklists": { + "spamhaus_dbl": "not listed", + "surbl": "not listed" + }, + "larted": true, + "tags": [ + "32-bit", + "elf", + "mips" + ], + "threat": "malware_download", + "url_status": "online" + } + } + } + } +} + +{ + "type": "doc", + "value": { + "id": "978787", + "index": "filebeat-8.0.0-2021.01.26-000001", + "source": { + "@timestamp": "2021-01-26T11:09:05.529Z", + "agent": { + "ephemeral_id": "b7b56c3e-1f27-4c69-96f4-aa9ca47888d0", + "id": "69acb5f0-1e79-4cfe-a4dc-e0dbf229ff51", + "name": "MacBook-Pro-de-Gloria.local", + "type": "filebeat", + "version": "8.0.0" + }, + "ecs": { + "version": "1.6.0" + }, + "event": { + "category": "threat", + "created": "2021-01-26T11:09:05.529Z", + "dataset": "ti_abusech.malware", + "ingested": "2021-01-26T11:09:06.616763Z", + "kind": "enrichment", + "module": "threatintel", + "reference": "https://urlhaus.abuse.ch/url/978782/", + "type": "indicator" + }, + "fileset": { + "name": "abuseurl" + }, + "input": { + "type": "httpjson" + }, + "service": { + "type": "threatintel" + }, + "tags": [ + "threatintel-abuseurls", + "forwarded" + ], + "threat": { + "indicator": { + "description": "this should match auditbeat/hosts on ip", + "ip": "45.115.45.3", + "first_seen": "2021-01-26T11:06:03.000Z", + "provider": "other_provider", + "type": "ip" + } + }, + "threatintel": { + "abuseurl": { + "blacklists": { + "spamhaus_dbl": "not listed", + "surbl": "not listed" + }, + "larted": true, + "tags": [ + "32-bit", + "elf", + "mips" + ], + "threat": "malware_download", + "url_status": "online" + } + } + } + } +} + +{ + "type": "doc", + "value": { + "id": "978766", + "index": "filebeat-8.0.0-2021.01.26-000001", + "source": { + "@timestamp": "2021-01-26T11:09:05.529Z", + "agent": { + "ephemeral_id": "b7b56c3e-1f27-4c69-96f4-aa9ca47888d0", + "id": "69acb5f0-1e79-4cfe-a4dc-e0dbf229ff51", + "name": "MacBook-Pro-de-Gloria.local", + "type": "filebeat", + "version": "8.0.0" + }, + "ecs": { + "version": "1.6.0" + }, + "event": { + "category": "threat", + "created": "2021-01-26T11:09:05.529Z", + "dataset": "ti_abusech.malware", + "ingested": "2021-01-26T11:09:06.595350Z", + "kind": "enrichment", + "module": "threatintel", + "reference": "https://urlhaus.abuse.ch/url/978783/", + "type": "indicator" + }, + "fileset": { + "name": "abuseurl" + }, + "input": { + "type": "httpjson" + }, + "service": { + "type": "threatintel" + }, + "tags": [ + "threatintel-abuseurls", + "forwarded" + ], + "threat": { + "indicator": { + "description": "domain should match the auditbeat hosts' data's source.ip", + "domain": "172.16.0.0", + "ip": "8.8.8.8", + "port": 777, + "first_seen": "2021-01-26T11:09:04.000Z", + "provider": "geenensp", + "type": "url", + "url": { + "full": "http://159.89.119.67:59600/bin.sh", + "scheme": "http" + } + } + }, + "threatintel": { + "abuseurl": { + "blacklists": { + "spamhaus_dbl": "not listed", + "surbl": "not listed" + }, + "larted": false, + "tags": null, + "threat": "malware_download", + "url_status": "online" + } + } + } + } +} + +{ + "type": "doc", + "value": { + "id": "978767", + "index": "filebeat-8.0.0-2021.01.26-000001", + "source": { + "@timestamp": "2021-01-26T11:09:05.529Z", + "agent": { + "ephemeral_id": "b7b56c3e-1f27-4c69-96f4-aa9ca47888d0", + "id": "69acb5f0-1e79-4cfe-a4dc-e0dbf229ff51", + "name": "MacBook-Pro-de-Gloria.local", + "type": "filebeat", + "version": "8.0.0" + }, + "ecs": { + "version": "1.6.0" + }, + "event": { + "category": "threat", + "created": "2021-01-26T11:09:05.529Z", + "dataset": "ti_abusech.malware", + "ingested": "2021-01-26T11:09:06.595350Z", + "kind": "enrichment", + "module": "threatintel", + "reference": "https://urlhaus.abuse.ch/url/978783/", + "type": "indicator" + }, + "fileset": { + "name": "abuseurl" + }, + "input": { + "type": "httpjson" + }, + "service": { + "type": "threatintel" + }, + "tags": [ + "threatintel-abuseurls", + "forwarded" + ], + "threat": { + "indicator": { + "description": "domain should match the auditbeat hosts' data's source.ip", + "domain": "172.16.0.0", + "ip": "9.9.9.9", + "port": 123, + "first_seen": "2021-01-26T11:09:04.000Z", + "provider": "geenensp", + "type": "url", + "url": { + "full": "http://159.89.119.67:59600/bin.sh", + "scheme": "http" + } + } + }, + "threatintel": { + "abuseurl": { + "blacklists": { + "spamhaus_dbl": "not listed", + "surbl": "not listed" + }, + "larted": false, + "tags": null, + "threat": "malware_download", + "url_status": "online" + } + } + } + } +} \ No newline at end of file diff --git a/x-pack/test/security_solution_api_integration/es_archive/serverless/filebeat/threat_intel/mappings.json b/x-pack/test/security_solution_api_integration/es_archive/serverless/filebeat/threat_intel/mappings.json new file mode 100644 index 0000000000000..eda2430daef92 --- /dev/null +++ b/x-pack/test/security_solution_api_integration/es_archive/serverless/filebeat/threat_intel/mappings.json @@ -0,0 +1,240 @@ +{ + "type": "index", + "value": { + "aliases": {}, + "index": "filebeat-8.0.0-2021.01.26-000001", + "mappings": { + "_meta": { + "beat": "filebeat", + "version": "7.0.0" + }, + "properties": { + "@timestamp": { + "type": "date" + }, + "@version": { + "ignore_above": 1024, + "type": "keyword" + }, + "threat": { + "properties": { + "framework": { + "ignore_above": 1024, + "type": "keyword" + }, + "indicator": { + "properties": { + "as": { + "properties": { + "number": { + "type": "long" + }, + "organization": { + "properties": { + "name": { + "fields": { + "text": { + "norms": false, + "type": "text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "confidence": { + "ignore_above": 1024, + "type": "keyword" + }, + "dataset": { + "ignore_above": 1024, + "type": "keyword" + }, + "description": { + "type": "wildcard" + }, + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "email": { + "properties": { + "address": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "first_seen": { + "type": "date" + }, + "geo": { + "properties": { + "city_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "continent_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "country_iso_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "country_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "location": { + "type": "geo_point" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "region_iso_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "region_name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "ip": { + "type": "ip" + }, + "last_seen": { + "type": "date" + }, + "marking": { + "properties": { + "tlp": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "matched": { + "properties": { + "atomic": { + "ignore_above": 1024, + "type": "keyword" + }, + "field": { + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "module": { + "ignore_above": 1024, + "type": "keyword" + }, + "port": { + "type": "long" + }, + "provider": { + "ignore_above": 1024, + "type": "keyword" + }, + "scanner_stats": { + "type": "long" + }, + "sightings": { + "type": "long" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "tactic": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "reference": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "technique": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "norms": false, + "type": "text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "reference": { + "ignore_above": 1024, + "type": "keyword" + }, + "subtechnique": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "norms": false, + "type": "text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "reference": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + } + } + } + } + }, + "settings": { + "index": { + "auto_expand_replicas": "0-1", + "mapping": { + "total_fields": { + "limit": "10000" + } + }, + "number_of_replicas": "0", + "number_of_shards": "1", + "refresh_interval": "5s" + } + } + } +} diff --git a/x-pack/test/security_solution_api_integration/package.json b/x-pack/test/security_solution_api_integration/package.json index 89f6e0f164f8e..50dc47f95b1b3 100644 --- a/x-pack/test/security_solution_api_integration/package.json +++ b/x-pack/test/security_solution_api_integration/package.json @@ -19,11 +19,26 @@ "exception_operators_date_numeric_types:qa:serverless": "npm run run-tests:dr:default exceptions/operators_data_types/date_numeric_types serverless qaEnv", "exception_operators_date_numeric_types:server:ess": "npm run initialize-server:dr:default exceptions/operators_data_types/date_numeric_types ess", "exception_operators_date_numeric_types:runner:ess": "npm run run-tests:dr:default exceptions/operators_data_types/date_numeric_types ess essEnv", - "exception_operators_keyword_text_long:server:serverless": "npm run initialize-server:dr:default exceptions/operators_data_types/keyword_text_long serverless", - "exception_operators_keyword_text_long:runner:serverless": "npm run run-tests:dr:default exceptions/operators_data_types/keyword_text_long serverless serverlessEnv", - "exception_operators_keyword_text_long:qa:serverless": "npm run run-tests:dr:default exceptions/operators_data_types/keyword_text_long serverless qaEnv", - "exception_operators_keyword_text_long:server:ess": "npm run initialize-server:dr:default exceptions/operators_data_types/keyword_text_long ess", - "exception_operators_keyword_text_long:runner:ess": "npm run run-tests:dr:default exceptions/operators_data_types/keyword_text_long ess essEnv", + "exception_operators_keyword:server:serverless": "npm run initialize-server:dr:default exceptions/operators_data_types/keyword serverless", + "exception_operators_keyword:runner:serverless": "npm run run-tests:dr:default exceptions/operators_data_types/keyword serverless serverlessEnv", + "exception_operators_keyword:qa:serverless": "npm run run-tests:dr:default exceptions/operators_data_types/keyword serverless qaEnv", + "exception_operators_keyword:server:ess": "npm run initialize-server:dr:default exceptions/operators_data_types/keyword ess", + "exception_operators_keyword:runner:ess": "npm run run-tests:dr:default exceptions/operators_data_types/keyword ess essEnv", + "exception_operators_ips:server:serverless": "npm run initialize-server:dr:default exceptions/operators_data_types/ips serverless", + "exception_operators_ips:runner:serverless": "npm run run-tests:dr:default exceptions/operators_data_types/ips serverless serverlessEnv", + "exception_operators_ips:qa:serverless": "npm run run-tests:dr:default exceptions/operators_data_types/ips serverless qaEnv", + "exception_operators_ips:server:ess": "npm run initialize-server:dr:default exceptions/operators_data_types/ips ess", + "exception_operators_ips:runner:ess": "npm run run-tests:dr:default exceptions/operators_data_types/ips ess essEnv", + "exception_operators_long:server:serverless": "npm run initialize-server:dr:default exceptions/operators_data_types/long serverless", + "exception_operators_long:runner:serverless": "npm run run-tests:dr:default exceptions/operators_data_types/long serverless serverlessEnv", + "exception_operators_long:qa:serverless": "npm run run-tests:dr:default exceptions/operators_data_types/long serverless qaEnv", + "exception_operators_long:server:ess": "npm run initialize-server:dr:default exceptions/operators_data_types/long ess", + "exception_operators_long:runner:ess": "npm run run-tests:dr:default exceptions/operators_data_types/long ess essEnv", + "exception_operators_text:server:serverless": "npm run initialize-server:dr:default exceptions/operators_data_types/text serverless", + "exception_operators_text:runner:serverless": "npm run run-tests:dr:default exceptions/operators_data_types/text serverless serverlessEnv", + "exception_operators_text:qa:serverless": "npm run run-tests:dr:default exceptions/operators_data_types/text serverless qaEnv", + "exception_operators_text:server:ess": "npm run initialize-server:dr:default exceptions/operators_data_types/text ess", + "exception_operators_text:runner:ess": "npm run run-tests:dr:default exceptions/operators_data_types/text ess essEnv", "exception_operators_ips_text_array:server:serverless": "npm run initialize-server:dr:default exceptions/operators_data_types/ips_text_array serverless", "exception_operators_ips_text_array:runner:serverless": "npm run run-tests:dr:default exceptions/operators_data_types/ips_text_array serverless serverlessEnv", "exception_operators_ips_text_array:qa:serverless": "npm run run-tests:dr:default exceptions/operators_data_types/ips_text_array serverless qaEnv", @@ -68,6 +83,21 @@ "prebuilt_rules_update_prebuilt_rules_package:runner:serverless": "npm run run-tests:dr:default prebuilt_rules/update_prebuilt_rules_package serverless serverlessEnv", "prebuilt_rules_update_prebuilt_rules_package:qa:serverless": "npm run run-tests:dr:default prebuilt_rules/update_prebuilt_rules_package serverless qaEnv", "prebuilt_rules_update_prebuilt_rules_package:server:ess": "npm run initialize-server:dr:default prebuilt_rules/update_prebuilt_rules_package ess", - "prebuilt_rules_update_prebuilt_rules_package:runner:ess": "npm run run-tests:dr:default prebuilt_rules/update_prebuilt_rules_package ess essEnvs" + "prebuilt_rules_update_prebuilt_rules_package:runner:ess": "npm run run-tests:dr:default prebuilt_rules/update_prebuilt_rules_package ess essEnvs", + "rule_execution_logic:server:serverless": "npm run initialize-server:dr:default rule_execution_logic serverless", + "rule_execution_logic:runner:serverless": "npm run run-tests:dr:default rule_execution_logic serverless serverlessEnv", + "rule_execution_logic:qa:serverless": "npm run run-tests:dr:default rule_execution_logic serverless qaEnv", + "rule_execution_logic:server:ess": "npm run initialize-server:dr:default rule_execution_logic ess", + "rule_execution_logic:runner:ess": "npm run run-tests:dr:default rule_execution_logic ess essEnv", + "user_roles:server:serverless": "npm run initialize-server:dr:default user_roles serverless", + "user_roles:runner:serverless": "npm run run-tests:dr:default user_roles serverless serverlessEnv", + "user_roles:qa:serverless": "npm run run-tests:dr:default user_roles serverless qaEnv", + "user_roles:server:ess": "npm run initialize-server:dr:default user_roles ess", + "user_roles:runner:ess": "npm run run-tests:dr:default user_roles ess essEnv", + "telemetry:server:serverless": "npm run initialize-server:dr:default telemetry serverless", + "telemetry:runner:serverless": "npm run run-tests:dr:default telemetry serverless serverlessEnv", + "telemetry:qa:serverless": "npm run run-tests:dr:default telemetry serverless qaEnv", + "telemetry:server:ess": "npm run initialize-server:dr:default telemetry ess", + "telemetry:runner:ess": "npm run run-tests:dr:default telemetry ess essEnv" } } diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/actions/add_actions.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/actions/add_actions.ts index 8046eb89e0a28..1e4b1692cf9fc 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/actions/add_actions.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/actions/add_actions.ts @@ -6,7 +6,7 @@ */ import expect from 'expect'; - +import { ELASTIC_HTTP_VERSION_HEADER } from '@kbn/core-http-common'; import { DETECTION_ENGINE_RULES_URL } from '@kbn/security-solution-plugin/common/constants'; import { deleteAllRules, @@ -55,7 +55,7 @@ export default ({ getService }: FtrProviderContext) => { const { body } = await supertest .post(DETECTION_ENGINE_RULES_URL) .set('kbn-xsrf', 'true') - .set('elastic-api-version', '2023-10-31') + .set(ELASTIC_HTTP_VERSION_HEADER, '2023-10-31') .send( getCustomQueryRuleParams({ actions: [ruleAction], @@ -74,7 +74,7 @@ export default ({ getService }: FtrProviderContext) => { } = await supertest .post(DETECTION_ENGINE_RULES_URL) .set('kbn-xsrf', 'true') - .set('elastic-api-version', '2023-10-31') + .set(ELASTIC_HTTP_VERSION_HEADER, '2023-10-31') .send( getCustomQueryRuleParams({ index: ['logs-test'], @@ -108,7 +108,7 @@ export default ({ getService }: FtrProviderContext) => { } = await supertest .post(DETECTION_ENGINE_RULES_URL) .set('kbn-xsrf', 'true') - .set('elastic-api-version', '2023-10-31') + .set(ELASTIC_HTTP_VERSION_HEADER, '2023-10-31') .send( getCustomQueryRuleParams({ index: ['logs-test'], diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/group1/check_privileges.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/actions/check_privileges.ts similarity index 89% rename from x-pack/test/detection_engine_api_integration/security_and_spaces/group1/check_privileges.ts rename to x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/actions/check_privileges.ts index 3a016fe68618d..cbcd75074b57c 100644 --- a/x-pack/test/detection_engine_api_integration/security_and_spaces/group1/check_privileges.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/actions/check_privileges.ts @@ -9,19 +9,22 @@ import expect from '@kbn/expect'; import { DETECTION_ENGINE_RULES_URL } from '@kbn/security-solution-plugin/common/constants'; import { ROLES } from '@kbn/security-solution-plugin/common/test'; import { ThresholdRuleCreateProps } from '@kbn/security-solution-plugin/common/api/detection_engine'; -import { FtrProviderContext } from '../../common/ftr_provider_context'; + import { - createSignalsIndex, + createAlertsIndex, deleteAllRules, waitForRulePartialFailure, - getRuleForSignalTesting, + getRuleForAlertTesting, createRuleWithAuth, - getThresholdRuleForSignalTesting, + getThresholdRuleForAlertTesting, deleteAllAlerts, } from '../../utils'; -import { createUserAndRole, deleteUserAndRole } from '../../../common/services/security_solution'; +import { + createUserAndRole, + deleteUserAndRole, +} from '../../../../../common/services/security_solution'; -// eslint-disable-next-line import/no-default-export +import { FtrProviderContext } from '../../../../ftr_provider_context'; export default ({ getService }: FtrProviderContext) => { const supertest = getService('supertest'); const esArchiver = getService('esArchiver'); @@ -29,11 +32,11 @@ export default ({ getService }: FtrProviderContext) => { const log = getService('log'); const es = getService('es'); - describe('check_privileges', () => { + describe('@ess @serverless @brokenInServerless check_privileges', () => { before(async () => { await esArchiver.load('x-pack/test/functional/es_archives/auditbeat/hosts'); await esArchiver.load('x-pack/test/functional/es_archives/security_solution/alias'); - await createSignalsIndex(supertest, log); + await createAlertsIndex(supertest, log); }); after(async () => { @@ -60,7 +63,7 @@ export default ({ getService }: FtrProviderContext) => { indexTestCases.forEach((index) => { it(`for KQL rule with index param: ${index}`, async () => { const rule = { - ...getRuleForSignalTesting(index), + ...getRuleForAlertTesting(index), query: 'process.executable: "/usr/bin/sudo"', }; await createUserAndRole(getService, ROLES.detections_admin); @@ -96,7 +99,7 @@ export default ({ getService }: FtrProviderContext) => { thresholdIndexTestCases.forEach((index) => { it(`for threshold rule with index param: ${index}`, async () => { const rule: ThresholdRuleCreateProps = { - ...getThresholdRuleForSignalTesting(index), + ...getThresholdRuleForAlertTesting(index), threshold: { field: [], value: 700, diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/actions/index.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/actions/index.ts index 5c26d445eb158..4eb7f7eac6978 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/actions/index.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/actions/index.ts @@ -11,5 +11,7 @@ export default function ({ loadTestFile }: FtrProviderContext) { loadTestFile(require.resolve('./add_actions')); loadTestFile(require.resolve('./update_actions')); loadTestFile(require.resolve('./migrations')); + loadTestFile(require.resolve('./throttle')); + loadTestFile(require.resolve('./check_privileges')); }); } diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/group10/throttle.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/actions/throttle.ts similarity index 78% rename from x-pack/test/detection_engine_api_integration/security_and_spaces/group10/throttle.ts rename to x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/actions/throttle.ts index 34984d4ea0dc8..ee5d81b9f29fb 100644 --- a/x-pack/test/detection_engine_api_integration/security_and_spaces/group10/throttle.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/actions/throttle.ts @@ -13,20 +13,24 @@ import { NOTIFICATION_THROTTLE_NO_ACTIONS, NOTIFICATION_THROTTLE_RULE, } from '@kbn/security-solution-plugin/common/constants'; -import { FtrProviderContext } from '../../common/ftr_provider_context'; import { - createSignalsIndex, + ELASTIC_HTTP_VERSION_HEADER, + X_ELASTIC_INTERNAL_ORIGIN_REQUEST, +} from '@kbn/core-http-common'; +import { + createAlertsIndex, deleteAllRules, deleteAllAlerts, getWebHookAction, getRuleWithWebHookAction, createRule, getSimpleRule, - getRule, + fetchRule, updateRule, } from '../../utils'; -// eslint-disable-next-line import/no-default-export +import { FtrProviderContext } from '../../../../ftr_provider_context'; + export default ({ getService }: FtrProviderContext) => { const supertest = getService('supertest'); const log = getService('log'); @@ -45,10 +49,10 @@ export default ({ getService }: FtrProviderContext) => { * https://www.elastic.co/guide/en/kibana/current/mute-all-alerts-api.html * https://www.elastic.co/guide/en/security/current/rules-api-create.html */ - describe('throttle', () => { + describe('@ess @serverless throttle', () => { describe('adding actions', () => { beforeEach(async () => { - await createSignalsIndex(supertest, log); + await createAlertsIndex(supertest, log); }); afterEach(async () => { @@ -62,13 +66,17 @@ export default ({ getService }: FtrProviderContext) => { const { body: hookAction } = await supertest .post('/api/actions/action') .set('kbn-xsrf', 'true') + .set(ELASTIC_HTTP_VERSION_HEADER, '2023-10-31') + .set(X_ELASTIC_INTERNAL_ORIGIN_REQUEST, 'kibana') .send(getWebHookAction()) .expect(200); const rule = await createRule(supertest, log, getRuleWithWebHookAction(hookAction.id)); const { body: { mute_all: muteAll, notify_when: notifyWhen, actions }, - } = await supertest.get(`/api/alerting/rule/${rule.id}`); + } = await supertest + .get(`/api/alerting/rule/${rule.id}`) + .set(X_ELASTIC_INTERNAL_ORIGIN_REQUEST, 'kibana'); expect(muteAll).to.eql(false); expect(actions.length).to.eql(1); expect(actions[0].frequency).to.eql({ @@ -87,7 +95,9 @@ export default ({ getService }: FtrProviderContext) => { const rule = await createRule(supertest, log, ruleWithThrottle); const { body: { mute_all: muteAll, notify_when: notifyWhen }, - } = await supertest.get(`/api/alerting/rule/${rule.id}`); + } = await supertest + .get(`/api/alerting/rule/${rule.id}`) + .set(X_ELASTIC_INTERNAL_ORIGIN_REQUEST, 'kibana'); expect(muteAll).to.eql(false); expect(notifyWhen).to.eql(null); }); @@ -97,6 +107,7 @@ export default ({ getService }: FtrProviderContext) => { const { body: hookAction } = await supertest .post('/api/actions/action') .set('kbn-xsrf', 'true') + .set(X_ELASTIC_INTERNAL_ORIGIN_REQUEST, 'kibana') .send(getWebHookAction()) .expect(200); @@ -107,7 +118,9 @@ export default ({ getService }: FtrProviderContext) => { const rule = await createRule(supertest, log, ruleWithThrottle); const { body: { mute_all: muteAll, notify_when: notifyWhen }, - } = await supertest.get(`/api/alerting/rule/${rule.id}`); + } = await supertest + .get(`/api/alerting/rule/${rule.id}`) + .set(X_ELASTIC_INTERNAL_ORIGIN_REQUEST, 'kibana'); expect(muteAll).to.eql(false); expect(notifyWhen).to.eql(null); }); @@ -120,7 +133,9 @@ export default ({ getService }: FtrProviderContext) => { const rule = await createRule(supertest, log, ruleWithThrottle); const { body: { mute_all: muteAll, notify_when: notifyWhen }, - } = await supertest.get(`/api/alerting/rule/${rule.id}`); + } = await supertest + .get(`/api/alerting/rule/${rule.id}`) + .set(X_ELASTIC_INTERNAL_ORIGIN_REQUEST, 'kibana'); expect(muteAll).to.eql(false); expect(notifyWhen).to.eql(null); }); @@ -140,6 +155,8 @@ export default ({ getService }: FtrProviderContext) => { const { body: hookAction } = await supertest .post('/api/actions/action') .set('kbn-xsrf', 'true') + .set(ELASTIC_HTTP_VERSION_HEADER, '2023-10-31') + .set(X_ELASTIC_INTERNAL_ORIGIN_REQUEST, 'kibana') .send(getWebHookAction()) .expect(200); @@ -150,7 +167,9 @@ export default ({ getService }: FtrProviderContext) => { const rule = await createRule(supertest, log, ruleWithThrottle); const { body: { mute_all: muteAll, notify_when: notifyWhen, actions }, - } = await supertest.get(`/api/alerting/rule/${rule.id}`); + } = await supertest + .get(`/api/alerting/rule/${rule.id}`) + .set(X_ELASTIC_INTERNAL_ORIGIN_REQUEST, 'kibana'); expect(muteAll).to.eql(false); expect(actions.length).to.eql(1); expect(actions[0].frequency).to.eql({ @@ -169,7 +188,9 @@ export default ({ getService }: FtrProviderContext) => { const rule = await createRule(supertest, log, ruleWithThrottle); const { body: { mute_all: muteAll, notify_when: notifyWhen }, - } = await supertest.get(`/api/alerting/rule/${rule.id}`); + } = await supertest + .get(`/api/alerting/rule/${rule.id}`) + .set(X_ELASTIC_INTERNAL_ORIGIN_REQUEST, 'kibana'); expect(muteAll).to.eql(false); expect(notifyWhen).to.eql(null); }); @@ -179,6 +200,8 @@ export default ({ getService }: FtrProviderContext) => { const { body: hookAction } = await supertest .post('/api/actions/action') .set('kbn-xsrf', 'true') + .set(ELASTIC_HTTP_VERSION_HEADER, '2023-10-31') + .set(X_ELASTIC_INTERNAL_ORIGIN_REQUEST, 'kibana') .send(getWebHookAction()) .expect(200); @@ -189,7 +212,9 @@ export default ({ getService }: FtrProviderContext) => { const rule = await createRule(supertest, log, ruleWithThrottle); const { body: { mute_all: muteAll, notify_when: notifyWhen, actions }, - } = await supertest.get(`/api/alerting/rule/${rule.id}`); + } = await supertest + .get(`/api/alerting/rule/${rule.id}`) + .set(X_ELASTIC_INTERNAL_ORIGIN_REQUEST, 'kibana'); expect(muteAll).to.eql(false); expect(actions.length).to.eql(1); expect(actions[0].frequency).to.eql({ @@ -207,11 +232,13 @@ export default ({ getService }: FtrProviderContext) => { const { body: hookAction } = await supertest .post('/api/actions/action') .set('kbn-xsrf', 'true') + .set(ELASTIC_HTTP_VERSION_HEADER, '2023-10-31') + .set(X_ELASTIC_INTERNAL_ORIGIN_REQUEST, 'kibana') .send(getWebHookAction()) .expect(200); const rule = await createRule(supertest, log, getRuleWithWebHookAction(hookAction.id)); - const readRule = await getRule(supertest, log, rule.rule_id); + const readRule = await fetchRule(supertest, { ruleId: rule.rule_id }); expect(readRule.throttle).to.eql(undefined); }); @@ -221,7 +248,7 @@ export default ({ getService }: FtrProviderContext) => { throttle: NOTIFICATION_THROTTLE_NO_ACTIONS, }; const rule = await createRule(supertest, log, ruleWithThrottle); - const readRule = await getRule(supertest, log, rule.rule_id); + const readRule = await fetchRule(supertest, { ruleId: rule.rule_id }); expect(readRule.throttle).to.eql(undefined); }); @@ -232,7 +259,7 @@ export default ({ getService }: FtrProviderContext) => { throttle: NOTIFICATION_THROTTLE_RULE, }; const rule = await createRule(supertest, log, ruleWithThrottle); - const readRule = await getRule(supertest, log, rule.rule_id); + const readRule = await fetchRule(supertest, { ruleId: rule.rule_id }); expect(readRule.throttle).to.eql(undefined); }); @@ -241,6 +268,8 @@ export default ({ getService }: FtrProviderContext) => { const { body: hookAction } = await supertest .post('/api/actions/action') .set('kbn-xsrf', 'true') + .set(ELASTIC_HTTP_VERSION_HEADER, '2023-10-31') + .set(X_ELASTIC_INTERNAL_ORIGIN_REQUEST, 'kibana') .send(getWebHookAction()) .expect(200); @@ -248,9 +277,11 @@ export default ({ getService }: FtrProviderContext) => { await supertest .post(`/api/alerting/rule/${rule.id}/_mute_all`) .set('kbn-xsrf', 'true') + .set(ELASTIC_HTTP_VERSION_HEADER, '2023-10-31') + .set(X_ELASTIC_INTERNAL_ORIGIN_REQUEST, 'kibana') .send() .expect(204); - const readRule = await getRule(supertest, log, rule.rule_id); + const readRule = await fetchRule(supertest, { ruleId: rule.rule_id }); expect(readRule.throttle).to.eql(undefined); }); }); @@ -261,13 +292,15 @@ export default ({ getService }: FtrProviderContext) => { const { body: hookAction } = await supertest .post('/api/actions/action') .set('kbn-xsrf', 'true') + .set(ELASTIC_HTTP_VERSION_HEADER, '2023-10-31') + .set(X_ELASTIC_INTERNAL_ORIGIN_REQUEST, 'kibana') .send(getWebHookAction()) .expect(200); const ruleWithWebHookAction = getRuleWithWebHookAction(hookAction.id); await createRule(supertest, log, ruleWithWebHookAction); ruleWithWebHookAction.name = 'some other name'; - const updated = await updateRule(supertest, log, ruleWithWebHookAction); + const updated = await updateRule(supertest, ruleWithWebHookAction); expect(updated.throttle).to.eql(undefined); }); @@ -276,16 +309,20 @@ export default ({ getService }: FtrProviderContext) => { const { body: hookAction } = await supertest .post('/api/actions/action') .set('kbn-xsrf', 'true') + .set(ELASTIC_HTTP_VERSION_HEADER, '2023-10-31') + .set(X_ELASTIC_INTERNAL_ORIGIN_REQUEST, 'kibana') .send(getWebHookAction()) .expect(200); const ruleWithWebHookAction = getRuleWithWebHookAction(hookAction.id); await createRule(supertest, log, ruleWithWebHookAction); ruleWithWebHookAction.name = 'some other name'; - const updated = await updateRule(supertest, log, ruleWithWebHookAction); + const updated = await updateRule(supertest, ruleWithWebHookAction); const { body: { mute_all: muteAll, notify_when: notifyWhen }, - } = await supertest.get(`/api/alerting/rule/${updated.id}`); + } = await supertest + .get(`/api/alerting/rule/${updated.id}`) + .set(X_ELASTIC_INTERNAL_ORIGIN_REQUEST, 'kibana'); expect(muteAll).to.eql(false); expect(notifyWhen).to.eql(null); }); @@ -296,13 +333,15 @@ export default ({ getService }: FtrProviderContext) => { const { body: hookAction } = await supertest .post('/api/actions/action') .set('kbn-xsrf', 'true') + .set(ELASTIC_HTTP_VERSION_HEADER, '2023-10-31') + .set(X_ELASTIC_INTERNAL_ORIGIN_REQUEST, 'kibana') .send(getWebHookAction()) .expect(200); const ruleWithWebHookAction = getRuleWithWebHookAction(hookAction.id); await createRule(supertest, log, ruleWithWebHookAction); ruleWithWebHookAction.actions = []; - const updated = await updateRule(supertest, log, ruleWithWebHookAction); + const updated = await updateRule(supertest, ruleWithWebHookAction); expect(updated.throttle).to.eql(undefined); }); }); @@ -313,6 +352,8 @@ export default ({ getService }: FtrProviderContext) => { const { body: hookAction } = await supertest .post('/api/actions/action') .set('kbn-xsrf', 'true') + .set(ELASTIC_HTTP_VERSION_HEADER, '2023-10-31') + .set(X_ELASTIC_INTERNAL_ORIGIN_REQUEST, 'kibana') .send(getWebHookAction()) .expect(200); @@ -322,10 +363,11 @@ export default ({ getService }: FtrProviderContext) => { await supertest .patch(DETECTION_ENGINE_RULES_URL) .set('kbn-xsrf', 'true') - .set('elastic-api-version', '2023-10-31') + .set(ELASTIC_HTTP_VERSION_HEADER, '2023-10-31') + .set(X_ELASTIC_INTERNAL_ORIGIN_REQUEST, 'kibana') .send({ rule_id: rule.rule_id, name: 'some other name' }) .expect(200); - const readRule = await getRule(supertest, log, rule.rule_id); + const readRule = await fetchRule(supertest, { ruleId: rule.rule_id }); expect(readRule.throttle).to.eql(undefined); }); @@ -334,6 +376,8 @@ export default ({ getService }: FtrProviderContext) => { const { body: hookAction } = await supertest .post('/api/actions/action') .set('kbn-xsrf', 'true') + .set(ELASTIC_HTTP_VERSION_HEADER, '2023-10-31') + .set(X_ELASTIC_INTERNAL_ORIGIN_REQUEST, 'kibana') .send(getWebHookAction()) .expect(200); @@ -343,12 +387,15 @@ export default ({ getService }: FtrProviderContext) => { await supertest .patch(DETECTION_ENGINE_RULES_URL) .set('kbn-xsrf', 'true') - .set('elastic-api-version', '2023-10-31') + .set(ELASTIC_HTTP_VERSION_HEADER, '2023-10-31') + .set(X_ELASTIC_INTERNAL_ORIGIN_REQUEST, 'kibana') .send({ rule_id: rule.rule_id, name: 'some other name' }) .expect(200); const { body: { mute_all: muteAll, notify_when: notifyWhen }, - } = await supertest.get(`/api/alerting/rule/${rule.id}`); + } = await supertest + .get(`/api/alerting/rule/${rule.id}`) + .set(X_ELASTIC_INTERNAL_ORIGIN_REQUEST, 'kibana'); expect(muteAll).to.eql(false); expect(notifyWhen).to.eql(null); }); @@ -359,6 +406,8 @@ export default ({ getService }: FtrProviderContext) => { const { body: hookAction } = await supertest .post('/api/actions/action') .set('kbn-xsrf', 'true') + .set(ELASTIC_HTTP_VERSION_HEADER, '2023-10-31') + .set(X_ELASTIC_INTERNAL_ORIGIN_REQUEST, 'kibana') .send(getWebHookAction()) .expect(200); @@ -368,10 +417,11 @@ export default ({ getService }: FtrProviderContext) => { await supertest .patch(DETECTION_ENGINE_RULES_URL) .set('kbn-xsrf', 'true') - .set('elastic-api-version', '2023-10-31') + .set(ELASTIC_HTTP_VERSION_HEADER, '2023-10-31') + .set(X_ELASTIC_INTERNAL_ORIGIN_REQUEST, 'kibana') .send({ rule_id: rule.rule_id, actions: [] }) .expect(200); - const readRule = await getRule(supertest, log, rule.rule_id); + const readRule = await fetchRule(supertest, { ruleId: rule.rule_id }); expect(readRule.throttle).to.eql(undefined); }); }); diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/alerts/alerts_compatibility.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/alerts/alerts_compatibility.ts index 9e4a9d05771d1..7df54659da8ce 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/alerts/alerts_compatibility.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/alerts/alerts_compatibility.ts @@ -36,7 +36,7 @@ import { waitFor, waitForRuleSuccess, waitForAlertsToBePresent, - removeRandomValuedProperties, + removeRandomValuedPropertiesFromAlert, } from '../../utils'; import { FtrProviderContext } from '../../../../ftr_provider_context'; @@ -231,11 +231,11 @@ export default ({ getService }: FtrProviderContext) => { expect(signalsOpen.hits.hits.length).greaterThan(0); const hit = signalsOpen.hits.hits[0]; expect(hit._source?.kibana).to.eql(undefined); - const source = removeRandomValuedProperties(hit._source); + const source = removeRandomValuedPropertiesFromAlert(hit._source); expect(source).to.eql({ 'kibana.alert.rule.category': 'Custom Query Rule', 'kibana.alert.rule.consumer': 'siem', - 'kibana.alert.rule.name': 'Signal Testing Query', + 'kibana.alert.rule.name': 'Alert Testing Query', 'kibana.alert.rule.producer': 'siem', 'kibana.alert.rule.rule_type_id': 'siem.queryRule', 'kibana.space_ids': ['default'], @@ -322,7 +322,7 @@ export default ({ getService }: FtrProviderContext) => { 'kibana.alert.workflow_tags': [], 'kibana.alert.depth': 2, 'kibana.alert.reason': - 'event on security-linux-1 created high alert Signal Testing Query.', + 'event on security-linux-1 created high alert Alert Testing Query.', 'kibana.alert.severity': 'high', 'kibana.alert.risk_score': 1, 'kibana.alert.rule.parameters': { @@ -393,11 +393,11 @@ export default ({ getService }: FtrProviderContext) => { expect(signalsOpen.hits.hits.length).greaterThan(0); const hit = signalsOpen.hits.hits[0]; expect(hit._source?.kibana).to.eql(undefined); - const source = removeRandomValuedProperties(hit._source); + const source = removeRandomValuedPropertiesFromAlert(hit._source); expect(source).to.eql({ 'kibana.alert.rule.category': 'Custom Query Rule', 'kibana.alert.rule.consumer': 'siem', - 'kibana.alert.rule.name': 'Signal Testing Query', + 'kibana.alert.rule.name': 'Alert Testing Query', 'kibana.alert.rule.producer': 'siem', 'kibana.alert.rule.rule_type_id': 'siem.queryRule', 'kibana.space_ids': ['default'], @@ -484,7 +484,7 @@ export default ({ getService }: FtrProviderContext) => { 'kibana.alert.workflow_tags': [], 'kibana.alert.depth': 2, 'kibana.alert.reason': - 'event on security-linux-1 created high alert Signal Testing Query.', + 'event on security-linux-1 created high alert Alert Testing Query.', 'kibana.alert.severity': 'high', 'kibana.alert.risk_score': 1, 'kibana.alert.rule.parameters': { diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/exceptions/operators_data_types/date_numeric_types/configs/ess.config.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/exceptions/operators_data_types/date_numeric_types/configs/ess.config.ts index ec10972a7062e..9d03e3503a480 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/exceptions/operators_data_types/date_numeric_types/configs/ess.config.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/exceptions/operators_data_types/date_numeric_types/configs/ess.config.ts @@ -17,7 +17,7 @@ export default async function ({ readConfigFile }: FtrConfigProviderContext) { testFiles: [require.resolve('..')], junit: { reportName: - 'Detection Engine ESS/ Exception Operators Data Types API date_numeric_types Integration Tests', + 'Detection Engine ESS - Exception Operators Data Types API - Date_numeric_types Integration Tests', }, }; } diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/exceptions/operators_data_types/date_numeric_types/configs/serverless.config.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/exceptions/operators_data_types/date_numeric_types/configs/serverless.config.ts index 3ec867abab432..df64ace832d80 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/exceptions/operators_data_types/date_numeric_types/configs/serverless.config.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/exceptions/operators_data_types/date_numeric_types/configs/serverless.config.ts @@ -11,6 +11,6 @@ export default createTestConfig({ testFiles: [require.resolve('..')], junit: { reportName: - 'Detection Engine Serverless/ Exception Operators Data Types date_numeric_types API Integration Tests', + 'Detection Engine Serverless - Exception Operators Data Types API - Date_numeric_types Integration Tests', }, }); diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/exceptions/operators_data_types/date_numeric_types/index.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/exceptions/operators_data_types/date_numeric_types/index.ts index 2ba798031818e..966bcfa8f269a 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/exceptions/operators_data_types/date_numeric_types/index.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/exceptions/operators_data_types/date_numeric_types/index.ts @@ -7,7 +7,7 @@ import { FtrProviderContext } from '../../../../../../ftr_provider_context'; export default ({ loadTestFile }: FtrProviderContext): void => { - describe('Detection exceptions data types and operators', function () { + describe('Detection exceptions data and numeric types', function () { loadTestFile(require.resolve('./date')); loadTestFile(require.resolve('./double')); loadTestFile(require.resolve('./float')); diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/exceptions/operators_data_types/ips_text_array/configs/ess.config.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/exceptions/operators_data_types/ips/configs/ess.config.ts similarity index 86% rename from x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/exceptions/operators_data_types/ips_text_array/configs/ess.config.ts rename to x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/exceptions/operators_data_types/ips/configs/ess.config.ts index 221f6d883bd35..114f4e628b7ac 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/exceptions/operators_data_types/ips_text_array/configs/ess.config.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/exceptions/operators_data_types/ips/configs/ess.config.ts @@ -17,7 +17,7 @@ export default async function ({ readConfigFile }: FtrConfigProviderContext) { testFiles: [require.resolve('..')], junit: { reportName: - 'Detection Engine ESS/ Exception Operators Data Types API ips_text_array Integration Tests', + 'Detection Engine ESS - Exception Operators Data Types API- IPS Integration Tests', }, }; } diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/exceptions/operators_data_types/ips_text_array/configs/serverless.config.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/exceptions/operators_data_types/ips/configs/serverless.config.ts similarity index 80% rename from x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/exceptions/operators_data_types/ips_text_array/configs/serverless.config.ts rename to x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/exceptions/operators_data_types/ips/configs/serverless.config.ts index c81563fdad84b..80ec0198524b3 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/exceptions/operators_data_types/ips_text_array/configs/serverless.config.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/exceptions/operators_data_types/ips/configs/serverless.config.ts @@ -11,6 +11,6 @@ export default createTestConfig({ testFiles: [require.resolve('..')], junit: { reportName: - 'Detection Engine Serverless/ Exception Operators Data Types ips_text_array API Integration Tests', + 'Detection Engine Serverless - Exception Operators Data Types API- IPS API Integration Tests', }, }); diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/group4/index.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/exceptions/operators_data_types/ips/index.ts similarity index 55% rename from x-pack/test/detection_engine_api_integration/security_and_spaces/group4/index.ts rename to x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/exceptions/operators_data_types/ips/index.ts index 9394e81017aba..ae58fe9aa371b 100644 --- a/x-pack/test/detection_engine_api_integration/security_and_spaces/group4/index.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/exceptions/operators_data_types/ips/index.ts @@ -5,11 +5,11 @@ * 2.0. */ -import { FtrProviderContext } from '../../common/ftr_provider_context'; +import { FtrProviderContext } from '../../../../../../ftr_provider_context'; -// eslint-disable-next-line import/no-default-export export default ({ loadTestFile }: FtrProviderContext): void => { - describe('detection engine api security and spaces enabled - Group 4', function () { - loadTestFile(require.resolve('./telemetry')); + describe('Detection exceptions IPs', function () { + loadTestFile(require.resolve('./ip')); + loadTestFile(require.resolve('./ip_array')); }); }; diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/exceptions/operators_data_types/ips_text_array/ip.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/exceptions/operators_data_types/ips/ip.ts similarity index 100% rename from x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/exceptions/operators_data_types/ips_text_array/ip.ts rename to x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/exceptions/operators_data_types/ips/ip.ts diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/exceptions/operators_data_types/ips_text_array/ip_array.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/exceptions/operators_data_types/ips/ip_array.ts similarity index 100% rename from x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/exceptions/operators_data_types/ips_text_array/ip_array.ts rename to x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/exceptions/operators_data_types/ips/ip_array.ts diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/exceptions/operators_data_types/keyword_text_long/configs/ess.config.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/exceptions/operators_data_types/keyword/configs/ess.config.ts similarity index 86% rename from x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/exceptions/operators_data_types/keyword_text_long/configs/ess.config.ts rename to x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/exceptions/operators_data_types/keyword/configs/ess.config.ts index b968919430064..8b19e9b0d8c6d 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/exceptions/operators_data_types/keyword_text_long/configs/ess.config.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/exceptions/operators_data_types/keyword/configs/ess.config.ts @@ -17,7 +17,7 @@ export default async function ({ readConfigFile }: FtrConfigProviderContext) { testFiles: [require.resolve('..')], junit: { reportName: - 'Detection Engine ESS/ Exception Operators Data Types API keyword_text_long Integration Tests', + 'Detection Engine ESS - Exception Operators Data Types API- Keyword Integration Tests', }, }; } diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/exceptions/operators_data_types/keyword_text_long/configs/serverless.config.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/exceptions/operators_data_types/keyword/configs/serverless.config.ts similarity index 80% rename from x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/exceptions/operators_data_types/keyword_text_long/configs/serverless.config.ts rename to x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/exceptions/operators_data_types/keyword/configs/serverless.config.ts index daf867a3a6839..3e209f3c04e85 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/exceptions/operators_data_types/keyword_text_long/configs/serverless.config.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/exceptions/operators_data_types/keyword/configs/serverless.config.ts @@ -11,6 +11,6 @@ export default createTestConfig({ testFiles: [require.resolve('..')], junit: { reportName: - 'Detection Engine Serverless/ Exception Operators Data Types keyword_text_long API Integration Tests', + 'Detection Engine Serverless - Exception Operators Data Types API - Keyword Integration Tests', }, }); diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/exceptions/operators_data_types/keyword_text_long/index.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/exceptions/operators_data_types/keyword/index.ts similarity index 75% rename from x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/exceptions/operators_data_types/keyword_text_long/index.ts rename to x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/exceptions/operators_data_types/keyword/index.ts index ad0a5d847b0fd..4325aa331f146 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/exceptions/operators_data_types/keyword_text_long/index.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/exceptions/operators_data_types/keyword/index.ts @@ -8,10 +8,8 @@ import { FtrProviderContext } from '../../../../../../ftr_provider_context'; export default ({ loadTestFile }: FtrProviderContext): void => { - describe('Detection exceptions data types and operators', function () { + describe('Detection exceptions Keyword', function () { loadTestFile(require.resolve('./keyword')); loadTestFile(require.resolve('./keyword_array')); - loadTestFile(require.resolve('./long')); - loadTestFile(require.resolve('./text')); }); }; diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/exceptions/operators_data_types/keyword_text_long/keyword.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/exceptions/operators_data_types/keyword/keyword.ts similarity index 100% rename from x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/exceptions/operators_data_types/keyword_text_long/keyword.ts rename to x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/exceptions/operators_data_types/keyword/keyword.ts diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/exceptions/operators_data_types/keyword_text_long/keyword_array.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/exceptions/operators_data_types/keyword/keyword_array.ts similarity index 100% rename from x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/exceptions/operators_data_types/keyword_text_long/keyword_array.ts rename to x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/exceptions/operators_data_types/keyword/keyword_array.ts diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/exceptions/operators_data_types/long/configs/ess.config.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/exceptions/operators_data_types/long/configs/ess.config.ts new file mode 100644 index 0000000000000..5438e929d9b22 --- /dev/null +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/exceptions/operators_data_types/long/configs/ess.config.ts @@ -0,0 +1,23 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { FtrConfigProviderContext } from '@kbn/test'; + +export default async function ({ readConfigFile }: FtrConfigProviderContext) { + const functionalConfig = await readConfigFile( + require.resolve('../../../../../../../config/ess/config.base.trial') + ); + + return { + ...functionalConfig.getAll(), + testFiles: [require.resolve('..')], + junit: { + reportName: + 'Detection Engine ESS - Exception Operators Data Types API - Long Integration Tests', + }, + }; +} diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/exceptions/operators_data_types/long/configs/serverless.config.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/exceptions/operators_data_types/long/configs/serverless.config.ts new file mode 100644 index 0000000000000..646062b09db91 --- /dev/null +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/exceptions/operators_data_types/long/configs/serverless.config.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 { createTestConfig } from '../../../../../../../config/serverless/config.base'; + +export default createTestConfig({ + testFiles: [require.resolve('..')], + junit: { + reportName: + 'Detection Engine Serverless - Exception Operators Data Types API - Long Integration Tests', + }, +}); diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/group5/index.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/exceptions/operators_data_types/long/index.ts similarity index 55% rename from x-pack/test/detection_engine_api_integration/security_and_spaces/group5/index.ts rename to x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/exceptions/operators_data_types/long/index.ts index ac107392d4b5c..2a1acd57cba39 100644 --- a/x-pack/test/detection_engine_api_integration/security_and_spaces/group5/index.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/exceptions/operators_data_types/long/index.ts @@ -5,11 +5,10 @@ * 2.0. */ -import { FtrProviderContext } from '../../common/ftr_provider_context'; +import { FtrProviderContext } from '../../../../../../ftr_provider_context'; -// eslint-disable-next-line import/no-default-export export default ({ loadTestFile }: FtrProviderContext): void => { - describe('detection engine api security and spaces enabled - Group 5', function () { - loadTestFile(require.resolve('./keyword_family')); + describe('Detection exceptions long', function () { + loadTestFile(require.resolve('./long')); }); }; diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/exceptions/operators_data_types/keyword_text_long/long.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/exceptions/operators_data_types/long/long.ts similarity index 100% rename from x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/exceptions/operators_data_types/keyword_text_long/long.ts rename to x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/exceptions/operators_data_types/long/long.ts diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/exceptions/operators_data_types/text/configs/ess.config.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/exceptions/operators_data_types/text/configs/ess.config.ts new file mode 100644 index 0000000000000..01bb5ebdd21eb --- /dev/null +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/exceptions/operators_data_types/text/configs/ess.config.ts @@ -0,0 +1,23 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { FtrConfigProviderContext } from '@kbn/test'; + +export default async function ({ readConfigFile }: FtrConfigProviderContext) { + const functionalConfig = await readConfigFile( + require.resolve('../../../../../../../config/ess/config.base.trial') + ); + + return { + ...functionalConfig.getAll(), + testFiles: [require.resolve('..')], + junit: { + reportName: + 'Detection Engine ESS - - Exception Operators Data Types API - Text Integration Tests', + }, + }; +} diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/exceptions/operators_data_types/text/configs/serverless.config.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/exceptions/operators_data_types/text/configs/serverless.config.ts new file mode 100644 index 0000000000000..3c67f4c7ad06c --- /dev/null +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/exceptions/operators_data_types/text/configs/serverless.config.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 { createTestConfig } from '../../../../../../../config/serverless/config.base'; + +export default createTestConfig({ + testFiles: [require.resolve('..')], + junit: { + reportName: + 'Detection Engine Serverless - Exception Operators Data Types API - Text Integration Tests', + }, +}); diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/exceptions/operators_data_types/ips_text_array/index.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/exceptions/operators_data_types/text/index.ts similarity index 85% rename from x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/exceptions/operators_data_types/ips_text_array/index.ts rename to x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/exceptions/operators_data_types/text/index.ts index 63f4639a96412..38354ffdcb365 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/exceptions/operators_data_types/ips_text_array/index.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/exceptions/operators_data_types/text/index.ts @@ -10,7 +10,6 @@ import { FtrProviderContext } from '../../../../../../ftr_provider_context'; export default ({ loadTestFile }: FtrProviderContext): void => { describe('Detection exceptions data types and operators', function () { loadTestFile(require.resolve('./text_array')); - loadTestFile(require.resolve('./ip')); - loadTestFile(require.resolve('./ip_array')); + loadTestFile(require.resolve('./text')); }); }; diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/exceptions/operators_data_types/keyword_text_long/text.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/exceptions/operators_data_types/text/text.ts similarity index 100% rename from x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/exceptions/operators_data_types/keyword_text_long/text.ts rename to x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/exceptions/operators_data_types/text/text.ts diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/exceptions/operators_data_types/ips_text_array/text_array.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/exceptions/operators_data_types/text/text_array.ts similarity index 100% rename from x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/exceptions/operators_data_types/ips_text_array/text_array.ts rename to x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/exceptions/operators_data_types/text/text_array.ts diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/exceptions/workflows/configs/ess.config.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/exceptions/workflows/configs/ess.config.ts index 19391784466d3..4a9004910d3b5 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/exceptions/workflows/configs/ess.config.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/exceptions/workflows/configs/ess.config.ts @@ -16,7 +16,7 @@ export default async function ({ readConfigFile }: FtrConfigProviderContext) { ...functionalConfig.getAll(), testFiles: [require.resolve('..')], junit: { - reportName: 'Detection Engine ESS/ Exception Workflows API Integration Tests', + reportName: 'Detection Engine ESS - Exception - Workflows API Integration Tests', }, }; } diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/exceptions/workflows/configs/serverless.config.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/exceptions/workflows/configs/serverless.config.ts index 1702c03591b64..32e5ca5e8d061 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/exceptions/workflows/configs/serverless.config.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/exceptions/workflows/configs/serverless.config.ts @@ -10,6 +10,6 @@ import { createTestConfig } from '../../../../../../config/serverless/config.bas export default createTestConfig({ testFiles: [require.resolve('..')], junit: { - reportName: 'Detection Engine Serverless/ Exception Workflows API Integration Tests', + reportName: 'Detection Engine Serverless - Exception - Workflows API Integration Tests', }, }); diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/prebuilt_rules/bundled_prebuilt_rules_package/install_latest_bundled_prebuilt_rules.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/prebuilt_rules/bundled_prebuilt_rules_package/install_latest_bundled_prebuilt_rules.ts index bd306b0d65654..556e689514d7f 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/prebuilt_rules/bundled_prebuilt_rules_package/install_latest_bundled_prebuilt_rules.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/prebuilt_rules/bundled_prebuilt_rules_package/install_latest_bundled_prebuilt_rules.ts @@ -66,7 +66,7 @@ export default ({ getService }: FtrProviderContext): void => { expect(bundledInstallResponse._meta.install_source).toBe('bundled'); // Refresh ES indices to avoid race conditions between write and reading of indeces - // See implementation utility function at x-pack/test/detection_engine_api_integration/utils/prebuilt_rules/install_prebuilt_rules_fleet_package.ts + // See implementation utility function at x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/prebuilt_rules/install_prebuilt_rules_fleet_package.ts await es.indices.refresh({ index: ALL_SAVED_OBJECT_INDICES }); // Verify that status is updated after package installation diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/rule_execution_logic/configs/ess.config.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/rule_execution_logic/configs/ess.config.ts new file mode 100644 index 0000000000000..bbf6c6c0e3f7b --- /dev/null +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/rule_execution_logic/configs/ess.config.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 { FtrConfigProviderContext } from '@kbn/test'; + +export default async function ({ readConfigFile }: FtrConfigProviderContext) { + const functionalConfig = await readConfigFile( + require.resolve('../../../../../config/ess/config.base.trial') + ); + + return { + ...functionalConfig.getAll(), + testFiles: [require.resolve('..')], + junit: { + reportName: 'Detection Engine API Integration Tests - ESS - Rule Execution Logic', + }, + }; +} diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/rule_execution_logic/configs/serverless.config.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/rule_execution_logic/configs/serverless.config.ts new file mode 100644 index 0000000000000..7bcb663699d68 --- /dev/null +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/rule_execution_logic/configs/serverless.config.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 { createTestConfig } from '../../../../../config/serverless/config.base'; + +export default createTestConfig({ + testFiles: [require.resolve('..')], + junit: { + reportName: 'Detection Engine API Integration Tests - Serverless - Rule Execution Logic', + }, + kbnTestServerArgs: [ + `--xpack.securitySolution.alertIgnoreFields=${JSON.stringify([ + 'testing_ignored.constant', + '/testing_regex*/', + ])}`, // See tests within the file "ignore_fields.ts" which use these values in "alertIgnoreFields" + ], +}); diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/rule_execution_logic/README.md b/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/rule_execution_logic/execution_logic/README.md similarity index 100% rename from x-pack/test/detection_engine_api_integration/security_and_spaces/rule_execution_logic/README.md rename to x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/rule_execution_logic/execution_logic/README.md diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/rule_execution_logic/eql.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/rule_execution_logic/execution_logic/eql.ts similarity index 79% rename from x-pack/test/detection_engine_api_integration/security_and_spaces/rule_execution_logic/eql.ts rename to x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/rule_execution_logic/execution_logic/eql.ts index b0469c90d8e4d..9cb85e3366cee 100644 --- a/x-pack/test/detection_engine_api_integration/security_and_spaces/rule_execution_logic/eql.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/rule_execution_logic/execution_logic/eql.ts @@ -27,35 +27,40 @@ import { ALERT_ORIGINAL_EVENT_CATEGORY, ALERT_GROUP_ID, } from '@kbn/security-solution-plugin/common/field_maps/field_names'; -import { getMaxSignalsWarning } from '@kbn/security-solution-plugin/server/lib/detection_engine/rule_types/utils/utils'; +import { getMaxSignalsWarning as getMaxAlertsWarning } from '@kbn/security-solution-plugin/server/lib/detection_engine/rule_types/utils/utils'; import { createRule, deleteAllRules, deleteAllAlerts, - getEqlRuleForSignalTesting, - getOpenSignals, + getEqlRuleForAlertTesting, + getOpenAlerts, getPreviewAlerts, previewRule, -} from '../../utils'; -import { FtrProviderContext } from '../../common/ftr_provider_context'; +} from '../../../utils'; +import { FtrProviderContext } from '../../../../../ftr_provider_context'; +import { EsArchivePathBuilder } from '../../../../../es_archive_path_builder'; -// eslint-disable-next-line import/no-default-export export default ({ getService }: FtrProviderContext) => { const supertest = getService('supertest'); const esArchiver = getService('esArchiver'); const es = getService('es'); const log = getService('log'); + // TODO: add a new service + const config = getService('config'); + const isServerless = config.get('serverless'); + const dataPathBuilder = new EsArchivePathBuilder(isServerless); + const auditPath = dataPathBuilder.getPath('auditbeat/hosts'); - describe('EQL type rules', () => { + describe('@ess @serverless EQL type rules', () => { before(async () => { - await esArchiver.load('x-pack/test/functional/es_archives/auditbeat/hosts'); + await esArchiver.load(auditPath); await esArchiver.load( 'x-pack/test/functional/es_archives/security_solution/timestamp_override_6' ); }); after(async () => { - await esArchiver.unload('x-pack/test/functional/es_archives/auditbeat/hosts'); + await esArchiver.unload(auditPath); await esArchiver.unload( 'x-pack/test/functional/es_archives/security_solution/timestamp_override_6' ); @@ -64,21 +69,21 @@ export default ({ getService }: FtrProviderContext) => { }); // First test creates a real rule - remaining tests use preview API - it('generates a correctly formatted signal from EQL non-sequence queries', async () => { + it('generates a correctly formatted alert from EQL non-sequence queries', async () => { const rule: EqlRuleCreateProps = { - ...getEqlRuleForSignalTesting(['auditbeat-*']), + ...getEqlRuleForAlertTesting(['auditbeat-*']), query: 'configuration where agent.id=="a1d7b39c-f898-4dbe-a761-efb61939302d"', }; const createdRule = await createRule(supertest, log, rule); - const alerts = await getOpenSignals(supertest, log, es, createdRule); + const alerts = await getOpenAlerts(supertest, log, es, createdRule); expect(alerts.hits.hits.length).eql(1); - const fullSignal = alerts.hits.hits[0]._source; - if (!fullSignal) { - return expect(fullSignal).to.be.ok(); + const fullAlert = alerts.hits.hits[0]._source; + if (!fullAlert) { + return expect(fullAlert).to.be.ok(); } - expect(fullSignal).eql({ - ...fullSignal, + expect(fullAlert).eql({ + ...fullAlert, agent: { ephemeral_id: '0010d67a-14f7-41da-be30-489fea735967', hostname: 'suricata-zeek-sensor-toronto', @@ -145,9 +150,9 @@ export default ({ getService }: FtrProviderContext) => { }, }, [ALERT_REASON]: - 'configuration event on suricata-zeek-sensor-toronto created high alert Signal Testing Query.', - [ALERT_RULE_UUID]: fullSignal[ALERT_RULE_UUID], - [ALERT_ORIGINAL_TIME]: fullSignal[ALERT_ORIGINAL_TIME], + 'configuration event on suricata-zeek-sensor-toronto created high alert Alert Testing Query.', + [ALERT_RULE_UUID]: fullAlert[ALERT_RULE_UUID], + [ALERT_ORIGINAL_TIME]: fullAlert[ALERT_ORIGINAL_TIME], [ALERT_WORKFLOW_STATUS]: 'open', [ALERT_WORKFLOW_TAGS]: [], [ALERT_DEPTH]: 1, @@ -167,41 +172,41 @@ export default ({ getService }: FtrProviderContext) => { }); }); - it('generates up to max_signals for non-sequence EQL queries', async () => { - const maxSignals = 200; + it('generates up to max_alerts for non-sequence EQL queries', async () => { + const maxAlerts = 200; const rule: EqlRuleCreateProps = { - ...getEqlRuleForSignalTesting(['auditbeat-*']), - max_signals: maxSignals, + ...getEqlRuleForAlertTesting(['auditbeat-*']), + max_signals: maxAlerts, }; const { previewId } = await previewRule({ supertest, rule }); - const previewAlerts = await getPreviewAlerts({ es, previewId, size: maxSignals * 2 }); - expect(previewAlerts.length).eql(maxSignals); + const previewAlerts = await getPreviewAlerts({ es, previewId, size: maxAlerts * 2 }); + expect(previewAlerts.length).eql(maxAlerts); }); - it('generates max signals warning when circuit breaker is hit', async () => { + it('generates max alerts warning when circuit breaker is hit', async () => { const rule: EqlRuleCreateProps = { - ...getEqlRuleForSignalTesting(['auditbeat-*']), + ...getEqlRuleForAlertTesting(['auditbeat-*']), }; const { logs } = await previewRule({ supertest, rule }); - expect(logs[0].warnings).contain(getMaxSignalsWarning()); + expect(logs[0].warnings).contain(getMaxAlertsWarning()); }); it('uses the provided event_category_override', async () => { const rule: EqlRuleCreateProps = { - ...getEqlRuleForSignalTesting(['auditbeat-*']), + ...getEqlRuleForAlertTesting(['auditbeat-*']), query: 'config_change where agent.id=="a1d7b39c-f898-4dbe-a761-efb61939302d"', event_category_override: 'auditd.message_type', }; const { previewId } = await previewRule({ supertest, rule }); const previewAlerts = await getPreviewAlerts({ es, previewId }); expect(previewAlerts.length).eql(1); - const fullSignal = previewAlerts[0]._source; - if (!fullSignal) { - return expect(fullSignal).to.be.ok(); + const fullAlert = previewAlerts[0]._source; + if (!fullAlert) { + return expect(fullAlert).to.be.ok(); } - expect(fullSignal).eql({ - ...fullSignal, + expect(fullAlert).eql({ + ...fullAlert, auditd: { data: { audit_enabled: '1', @@ -236,9 +241,9 @@ export default ({ getService }: FtrProviderContext) => { }, }, [ALERT_REASON]: - 'configuration event on suricata-zeek-sensor-toronto created high alert Signal Testing Query.', - [ALERT_RULE_UUID]: fullSignal[ALERT_RULE_UUID], - [ALERT_ORIGINAL_TIME]: fullSignal[ALERT_ORIGINAL_TIME], + 'configuration event on suricata-zeek-sensor-toronto created high alert Alert Testing Query.', + [ALERT_RULE_UUID]: fullAlert[ALERT_RULE_UUID], + [ALERT_ORIGINAL_TIME]: fullAlert[ALERT_ORIGINAL_TIME], [ALERT_WORKFLOW_STATUS]: 'open', [ALERT_DEPTH]: 1, [ALERT_ANCESTORS]: [ @@ -259,7 +264,7 @@ export default ({ getService }: FtrProviderContext) => { it('uses the provided timestamp_field', async () => { const rule: EqlRuleCreateProps = { - ...getEqlRuleForSignalTesting(['fake.index.1']), + ...getEqlRuleForAlertTesting(['fake.index.1']), query: 'any where true', timestamp_field: 'created_at', }; @@ -273,7 +278,7 @@ export default ({ getService }: FtrProviderContext) => { it('uses the provided tiebreaker_field', async () => { const rule: EqlRuleCreateProps = { - ...getEqlRuleForSignalTesting(['fake.index.1']), + ...getEqlRuleForAlertTesting(['fake.index.1']), query: 'any where true', tiebreaker_field: 'locale', }; @@ -285,9 +290,9 @@ export default ({ getService }: FtrProviderContext) => { expect(createdAtHits).to.eql(['es', 'pt', 'ua']); }); - it('generates building block signals from EQL sequences in the expected form', async () => { + it('generates building block alerts from EQL sequences in the expected form', async () => { const rule: EqlRuleCreateProps = { - ...getEqlRuleForSignalTesting(['auditbeat-*']), + ...getEqlRuleForAlertTesting(['auditbeat-*']), query: 'sequence by host.name [anomoly where true] [any where true]', // TODO: spelling }; const { previewId } = await previewRule({ supertest, rule }); @@ -298,13 +303,13 @@ export default ({ getService }: FtrProviderContext) => { get(alert._source, ALERT_ORIGINAL_EVENT_CATEGORY) === 'anomoly' ); expect(buildingBlock).not.eql(undefined); - const fullSignal = buildingBlock?._source; - if (!fullSignal) { - return expect(fullSignal).to.be.ok(); + const fullAlert = buildingBlock?._source; + if (!fullAlert) { + return expect(fullAlert).to.be.ok(); } - expect(fullSignal).eql({ - ...fullSignal, + expect(fullAlert).eql({ + ...fullAlert, agent: { ephemeral_id: '1b4978a0-48be-49b1-ac96-323425b389ab', hostname: 'zeek-sensor-amsterdam', @@ -409,10 +414,10 @@ export default ({ getService }: FtrProviderContext) => { }, }, [ALERT_REASON]: - 'anomoly event with process bro, by root on zeek-sensor-amsterdam created high alert Signal Testing Query.', - [ALERT_RULE_UUID]: fullSignal[ALERT_RULE_UUID], - [ALERT_GROUP_ID]: fullSignal[ALERT_GROUP_ID], - [ALERT_ORIGINAL_TIME]: fullSignal[ALERT_ORIGINAL_TIME], + 'anomoly event with process bro, by root on zeek-sensor-amsterdam created high alert Alert Testing Query.', + [ALERT_RULE_UUID]: fullAlert[ALERT_RULE_UUID], + [ALERT_GROUP_ID]: fullAlert[ALERT_GROUP_ID], + [ALERT_ORIGINAL_TIME]: fullAlert[ALERT_ORIGINAL_TIME], [ALERT_WORKFLOW_STATUS]: 'open', [ALERT_DEPTH]: 1, [ALERT_ANCESTORS]: [ @@ -431,9 +436,9 @@ export default ({ getService }: FtrProviderContext) => { }); }); - it('generates shell signals from EQL sequences in the expected form', async () => { + it('generates shell alerts from EQL sequences in the expected form', async () => { const rule: EqlRuleCreateProps = { - ...getEqlRuleForSignalTesting(['auditbeat-*']), + ...getEqlRuleForAlertTesting(['auditbeat-*']), query: 'sequence by host.name [anomoly where true] [any where true]', }; const { previewId } = await previewRule({ supertest, rule }); @@ -480,7 +485,7 @@ export default ({ getService }: FtrProviderContext) => { [ALERT_DEPTH]: 2, [ALERT_GROUP_ID]: source[ALERT_GROUP_ID], [ALERT_REASON]: - 'event by root on zeek-sensor-amsterdam created high alert Signal Testing Query.', + 'event by root on zeek-sensor-amsterdam created high alert Alert Testing Query.', [ALERT_RULE_UUID]: source[ALERT_RULE_UUID], [ALERT_ANCESTORS]: [ { @@ -513,28 +518,28 @@ export default ({ getService }: FtrProviderContext) => { }); }); - it('generates up to max_signals with an EQL rule', async () => { - const maxSignals = 200; + it('generates up to max_alerts with an EQL rule', async () => { + const maxAlerts = 200; const rule: EqlRuleCreateProps = { - ...getEqlRuleForSignalTesting(['auditbeat-*']), + ...getEqlRuleForAlertTesting(['auditbeat-*']), query: 'sequence by host.name [any where true] [any where true]', - max_signals: maxSignals, + max_signals: maxAlerts, }; const { previewId } = await previewRule({ supertest, rule }); - const previewAlerts = await getPreviewAlerts({ es, previewId, size: maxSignals * 5 }); - // For EQL rules, max_signals is the maximum number of detected sequences: each sequence has a building block - // alert for each event in the sequence, so max_signals=200 results in 400 building blocks in addition to + const previewAlerts = await getPreviewAlerts({ es, previewId, size: maxAlerts * 5 }); + // For EQL rules, max_alerts is the maximum number of detected sequences: each sequence has a building block + // alert for each event in the sequence, so max_alerts=200 results in 400 building blocks in addition to // 200 regular alerts - expect(previewAlerts.length).eql(maxSignals * 3); - const shellSignals = previewAlerts.filter((alert) => alert._source?.[ALERT_DEPTH] === 2); + expect(previewAlerts.length).eql(maxAlerts * 3); + const shellAlerts = previewAlerts.filter((alert) => alert._source?.[ALERT_DEPTH] === 2); const buildingBlocks = previewAlerts.filter((alert) => alert._source?.[ALERT_DEPTH] === 1); - expect(shellSignals.length).eql(maxSignals); - expect(buildingBlocks.length).eql(maxSignals * 2); + expect(shellAlerts.length).eql(maxAlerts); + expect(buildingBlocks.length).eql(maxAlerts * 2); }); - it('generates signals when an index name contains special characters to encode', async () => { + it('generates alerts when an index name contains special characters to encode', async () => { const rule: EqlRuleCreateProps = { - ...getEqlRuleForSignalTesting(['auditbeat-*', '']), + ...getEqlRuleForAlertTesting(['auditbeat-*', '']), query: 'configuration where agent.id=="a1d7b39c-f898-4dbe-a761-efb61939302d"', }; const { previewId } = await previewRule({ supertest, rule }); @@ -544,7 +549,7 @@ export default ({ getService }: FtrProviderContext) => { it('uses the provided filters', async () => { const rule: EqlRuleCreateProps = { - ...getEqlRuleForSignalTesting(['auditbeat-*']), + ...getEqlRuleForAlertTesting(['auditbeat-*']), query: 'any where true', filters: [ { @@ -599,18 +604,18 @@ export default ({ getService }: FtrProviderContext) => { it('should be enriched with host risk score', async () => { const rule: EqlRuleCreateProps = { - ...getEqlRuleForSignalTesting(['auditbeat-*']), + ...getEqlRuleForAlertTesting(['auditbeat-*']), query: 'configuration where agent.id=="a1d7b39c-f898-4dbe-a761-efb61939302d"', }; const { previewId } = await previewRule({ supertest, rule }); const previewAlerts = await getPreviewAlerts({ es, previewId }); expect(previewAlerts.length).eql(1); - const fullSignal = previewAlerts[0]._source; - if (!fullSignal) { - return expect(fullSignal).to.be.ok(); + const fullAlert = previewAlerts[0]._source; + if (!fullAlert) { + return expect(fullAlert).to.be.ok(); } - expect(fullSignal?.host?.risk?.calculated_level).to.eql('Critical'); - expect(fullSignal?.host?.risk?.calculated_score_norm).to.eql(96); + expect(fullAlert?.host?.risk?.calculated_level).to.eql('Critical'); + expect(fullAlert?.host?.risk?.calculated_score_norm).to.eql(96); }); }); }); diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/rule_execution_logic/esql.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/rule_execution_logic/execution_logic/esql.ts similarity index 96% rename from x-pack/test/detection_engine_api_integration/security_and_spaces/rule_execution_logic/esql.ts rename to x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/rule_execution_logic/execution_logic/esql.ts index 51db00fc1ed6b..e869854f0f44a 100644 --- a/x-pack/test/detection_engine_api_integration/security_and_spaces/rule_execution_logic/esql.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/rule_execution_logic/execution_logic/esql.ts @@ -13,23 +13,22 @@ import { EsqlRuleCreateProps } from '@kbn/security-solution-plugin/common/api/de import { getCreateEsqlRulesSchemaMock } from '@kbn/security-solution-plugin/common/api/detection_engine/model/rule_schema/mocks'; import { RuleExecutionStatusEnum } from '@kbn/security-solution-plugin/common/api/detection_engine/rule_monitoring'; -import { getMaxSignalsWarning } from '@kbn/security-solution-plugin/server/lib/detection_engine/rule_types/utils/utils'; +import { getMaxSignalsWarning as getMaxAlertsWarning } from '@kbn/security-solution-plugin/server/lib/detection_engine/rule_types/utils/utils'; import { deleteAllRules, deleteAllAlerts, getPreviewAlerts, previewRule, createRule, - getOpenSignals as getOpenAlerts, -} from '../../utils'; -import { FtrProviderContext } from '../../common/ftr_provider_context'; -import { previewRuleWithExceptionEntries } from '../../utils/preview_rule_with_exception_entries'; -import { deleteAllExceptions } from '../../../lists_api_integration/utils'; -import { dataGeneratorFactory } from '../../utils/data_generator'; -import { removeRandomValuedProperties } from './utils'; -import { patchRule } from '../../utils/patch_rule'; - -// eslint-disable-next-line import/no-default-export + getOpenAlerts, + dataGeneratorFactory, + previewRuleWithExceptionEntries, + removeRandomValuedPropertiesFromAlert, + patchRule, +} from '../../../utils'; +import { deleteAllExceptions } from '../../../../../../lists_api_integration/utils'; +import { FtrProviderContext } from '../../../../../ftr_provider_context'; + export default ({ getService }: FtrProviderContext) => { const supertest = getService('supertest'); const esArchiver = getService('esArchiver'); @@ -47,7 +46,7 @@ export default ({ getService }: FtrProviderContext) => { */ const internalIdPipe = (id: string) => `| where id=="${id}"`; - describe('ES|QL rule type', () => { + describe('@ess ES|QL rule type', () => { before(async () => { await esArchiver.load('x-pack/test/functional/es_archives/security_solution/ecs_compliant'); }); @@ -84,7 +83,7 @@ export default ({ getService }: FtrProviderContext) => { const alerts = await getOpenAlerts(supertest, log, es, createdRule); expect(alerts.hits.hits.length).toBe(1); - expect(removeRandomValuedProperties(alerts.hits.hits[0]._source)).toEqual({ + expect(removeRandomValuedPropertiesFromAlert(alerts.hits.hits[0]._source)).toEqual({ 'kibana.alert.rule.parameters': { description: 'Detecting root and admin users', risk_score: 55, @@ -602,8 +601,8 @@ export default ({ getService }: FtrProviderContext) => { }); }); - describe('max signals', () => { - it('generates max signals warning when circuit breaker is exceeded', async () => { + describe('max alerts', () => { + it('generates max alerts warning when circuit breaker is exceeded', async () => { const id = uuidv4(); const rule: EsqlRuleCreateProps = { ...getCreateEsqlRulesSchemaMock('rule-1', true), @@ -629,7 +628,7 @@ export default ({ getService }: FtrProviderContext) => { timeframeEnd: new Date('2020-10-28T06:30:00.000Z'), }); - expect(logs[0].warnings).toEqual(expect.arrayContaining([getMaxSignalsWarning()])); + expect(logs[0].warnings).toEqual(expect.arrayContaining([getMaxAlertsWarning()])); const previewAlerts = await getPreviewAlerts({ es, @@ -640,7 +639,7 @@ export default ({ getService }: FtrProviderContext) => { expect(previewAlerts.length).toBe(100); }); - it("doesn't generate max signals warning when circuit breaker is met but not exceeded", async () => { + it("doesn't generate max alerts warning when circuit breaker is met but not exceeded", async () => { const id = uuidv4(); const rule: EsqlRuleCreateProps = { ...getCreateEsqlRulesSchemaMock('rule-1', true), @@ -665,7 +664,7 @@ export default ({ getService }: FtrProviderContext) => { rule, timeframeEnd: new Date('2020-10-28T06:30:00.000Z'), }); - expect(logs[0].warnings).not.toEqual(expect.arrayContaining([getMaxSignalsWarning()])); + expect(logs[0].warnings).not.toEqual(expect.arrayContaining([getMaxAlertsWarning()])); const previewAlerts = await getPreviewAlerts({ es, @@ -676,7 +675,7 @@ export default ({ getService }: FtrProviderContext) => { expect(previewAlerts.length).toBe(100); }); - it('should work for max signals > 100', async () => { + it('should work for max alerts > 100', async () => { const id = uuidv4(); const rule: EsqlRuleCreateProps = { ...getCreateEsqlRulesSchemaMock('rule-1', true), diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/rule_execution_logic/index.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/rule_execution_logic/execution_logic/index.ts similarity index 77% rename from x-pack/test/detection_engine_api_integration/security_and_spaces/rule_execution_logic/index.ts rename to x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/rule_execution_logic/execution_logic/index.ts index e6cb1328c29b3..36a249304c7e6 100644 --- a/x-pack/test/detection_engine_api_integration/security_and_spaces/rule_execution_logic/index.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/rule_execution_logic/execution_logic/index.ts @@ -5,11 +5,10 @@ * 2.0. */ -import { FtrProviderContext } from '../../common/ftr_provider_context'; +import { FtrProviderContext } from '../../../../../ftr_provider_context'; -// eslint-disable-next-line import/no-default-export export default ({ loadTestFile }: FtrProviderContext): void => { - describe('detection engine api security and spaces enabled - rule execution logic', function () { + describe('Execution logic', function () { loadTestFile(require.resolve('./eql')); loadTestFile(require.resolve('./esql')); loadTestFile(require.resolve('./machine_learning')); @@ -18,7 +17,6 @@ export default ({ loadTestFile }: FtrProviderContext): void => { loadTestFile(require.resolve('./threat_match')); loadTestFile(require.resolve('./threshold')); loadTestFile(require.resolve('./non_ecs_fields')); - loadTestFile(require.resolve('./query')); }); }; diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/rule_execution_logic/machine_learning.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/rule_execution_logic/execution_logic/machine_learning.ts similarity index 81% rename from x-pack/test/detection_engine_api_integration/security_and_spaces/rule_execution_logic/machine_learning.ts rename to x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/rule_execution_logic/execution_logic/machine_learning.ts index 792fcb30b6645..3fd33d4ee8c90 100644 --- a/x-pack/test/detection_engine_api_integration/security_and_spaces/rule_execution_logic/machine_learning.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/rule_execution_logic/execution_logic/machine_learning.ts @@ -24,33 +24,38 @@ import { ALERT_DEPTH, ALERT_ORIGINAL_TIME, } from '@kbn/security-solution-plugin/common/field_maps/field_names'; -import { getMaxSignalsWarning } from '@kbn/security-solution-plugin/server/lib/detection_engine/rule_types/utils/utils'; +import { getMaxSignalsWarning as getMaxAlertsWarning } from '@kbn/security-solution-plugin/server/lib/detection_engine/rule_types/utils/utils'; import { expect } from 'expect'; import { createListsIndex, deleteAllExceptions, deleteListsIndex, importFile, -} from '../../../lists_api_integration/utils'; -import { FtrProviderContext } from '../../common/ftr_provider_context'; +} from '../../../../../../lists_api_integration/utils'; import { createRule, deleteAllRules, deleteAllAlerts, executeSetupModuleRequest, forceStartDatafeeds, - getOpenSignals, + getOpenAlerts, getPreviewAlerts, previewRule, previewRuleWithExceptionEntries, -} from '../../utils'; +} from '../../../utils'; +import { FtrProviderContext } from '../../../../../ftr_provider_context'; +import { EsArchivePathBuilder } from '../../../../../es_archive_path_builder'; -// eslint-disable-next-line import/no-default-export export default ({ getService }: FtrProviderContext) => { const supertest = getService('supertest'); const esArchiver = getService('esArchiver'); const es = getService('es'); const log = getService('log'); + // TODO: add a new service + const config = getService('config'); + const isServerless = config.get('serverless'); + const dataPathBuilder = new EsArchivePathBuilder(isServerless); + const auditPath = dataPathBuilder.getPath('auditbeat/hosts'); const siemModule = 'security_linux_v3'; const mlJobId = 'v3_linux_anomalous_network_activity'; @@ -66,17 +71,17 @@ export default ({ getService }: FtrProviderContext) => { rule_id: 'ml-rule-id', }; - describe('Machine learning type rules', () => { + describe('@ess @serverless Machine learning type rules', () => { before(async () => { // Order is critical here: auditbeat data must be loaded before attempting to start the ML job, // as the job looks for certain indices on start - await esArchiver.load('x-pack/test/functional/es_archives/auditbeat/hosts'); + await esArchiver.load(auditPath); await executeSetupModuleRequest({ module: siemModule, rspCode: 200, supertest }); await forceStartDatafeeds({ jobId: mlJobId, rspCode: 200, supertest }); await esArchiver.load('x-pack/test/functional/es_archives/security_solution/anomalies'); }); after(async () => { - await esArchiver.unload('x-pack/test/functional/es_archives/auditbeat/hosts'); + await esArchiver.unload(auditPath); await esArchiver.unload('x-pack/test/functional/es_archives/security_solution/anomalies'); await deleteAllAlerts(supertest, log, es); await deleteAllRules(supertest, log); @@ -85,11 +90,11 @@ export default ({ getService }: FtrProviderContext) => { // First test creates a real rule - remaining tests use preview API it('should create 1 alert from ML rule when record meets anomaly_threshold', async () => { const createdRule = await createRule(supertest, log, rule); - const alerts = await getOpenSignals(supertest, log, es, createdRule); + const alerts = await getOpenAlerts(supertest, log, es, createdRule); expect(alerts.hits.hits.length).toBe(1); - const signal = alerts.hits.hits[0]; + const alert = alerts.hits.hits[0]; - expect(signal._source).toEqual( + expect(alert._source).toEqual( expect.objectContaining({ '@timestamp': expect.any(String), [ALERT_RULE_EXECUTION_UUID]: expect.any(String), @@ -160,23 +165,23 @@ export default ({ getService }: FtrProviderContext) => { ); }); - it('generates max signals warning when circuit breaker is exceeded', async () => { + it('@skipInQA generates max alerts warning when circuit breaker is exceeded', async () => { const { logs } = await previewRule({ supertest, rule: { ...rule, anomaly_threshold: 1, max_signals: 5 }, // This threshold generates 10 alerts with the current esArchive }); - expect(logs[0].warnings).toContain(getMaxSignalsWarning()); + expect(logs[0].warnings).toContain(getMaxAlertsWarning()); }); - it("doesn't generate max signals warning when circuit breaker is met, but not exceeded", async () => { + it("doesn't generate max alerts warning when circuit breaker is met, but not exceeded", async () => { const { logs } = await previewRule({ supertest, rule: { ...rule, anomaly_threshold: 1, max_signals: 10 }, }); - expect(logs[0].warnings).not.toContain(getMaxSignalsWarning()); + expect(logs[0].warnings).not.toContain(getMaxAlertsWarning()); }); - it('should create 7 alerts from ML rule when records meet anomaly_threshold', async () => { + it('@skipInQA should create 7 alerts from ML rule when records meet anomaly_threshold', async () => { const { previewId } = await previewRule({ supertest, rule: { ...rule, anomaly_threshold: 20 }, @@ -189,7 +194,7 @@ export default ({ getService }: FtrProviderContext) => { afterEach(async () => { await deleteAllExceptions(supertest, log); }); - it('generates no signals when an exception is added for an ML rule', async () => { + it('generates no alerts when an exception is added for an ML rule', async () => { const { previewId } = await previewRuleWithExceptionEntries({ supertest, log, @@ -220,7 +225,7 @@ export default ({ getService }: FtrProviderContext) => { await deleteAllExceptions(supertest, log); }); - it('generates no signals when a value list exception is added for an ML rule', async () => { + it('generates no alerts when a value list exception is added for an ML rule', async () => { const valueListId = 'value-list-id'; await importFile(supertest, log, 'keyword', ['mothra'], valueListId); const { previewId } = await previewRuleWithExceptionEntries({ @@ -255,14 +260,14 @@ export default ({ getService }: FtrProviderContext) => { await esArchiver.unload('x-pack/test/functional/es_archives/entity/risks'); }); - it('should be enriched with host risk score', async () => { + it('@skipInQA should be enriched with host risk score', async () => { const { previewId } = await previewRule({ supertest, rule }); const previewAlerts = await getPreviewAlerts({ es, previewId }); expect(previewAlerts.length).toBe(1); - const fullSignal = previewAlerts[0]._source; + const fullAlert = previewAlerts[0]._source; - expect(fullSignal?.host?.risk?.calculated_level).toBe('Low'); - expect(fullSignal?.host?.risk?.calculated_score_norm).toBe(1); + expect(fullAlert?.host?.risk?.calculated_level).toBe('Low'); + expect(fullAlert?.host?.risk?.calculated_score_norm).toBe(1); }); }); }); diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/rule_execution_logic/new_terms.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/rule_execution_logic/execution_logic/new_terms.ts similarity index 95% rename from x-pack/test/detection_engine_api_integration/security_and_spaces/rule_execution_logic/new_terms.ts rename to x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/rule_execution_logic/execution_logic/new_terms.ts index 144d5e9bf51bd..0aedb19748cf4 100644 --- a/x-pack/test/detection_engine_api_integration/security_and_spaces/rule_execution_logic/new_terms.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/rule_execution_logic/execution_logic/new_terms.ts @@ -12,26 +12,25 @@ import { NewTermsRuleCreateProps } from '@kbn/security-solution-plugin/common/ap import { orderBy } from 'lodash'; import { getCreateNewTermsRulesSchemaMock } from '@kbn/security-solution-plugin/common/api/detection_engine/model/rule_schema/mocks'; -import { getMaxSignalsWarning } from '@kbn/security-solution-plugin/server/lib/detection_engine/rule_types/utils/utils'; +import { getMaxSignalsWarning as getMaxAlertsWarning } from '@kbn/security-solution-plugin/server/lib/detection_engine/rule_types/utils/utils'; import { createRule, deleteAllRules, deleteAllAlerts, - getOpenSignals, + getOpenAlerts, getPreviewAlerts, previewRule, -} from '../../utils'; -import { FtrProviderContext } from '../../common/ftr_provider_context'; -import { previewRuleWithExceptionEntries } from '../../utils/preview_rule_with_exception_entries'; -import { deleteAllExceptions } from '../../../lists_api_integration/utils'; -import { dataGeneratorFactory } from '../../utils/data_generator'; - -import { removeRandomValuedProperties } from './utils'; + dataGeneratorFactory, + previewRuleWithExceptionEntries, + removeRandomValuedPropertiesFromAlert, +} from '../../../utils'; +import { deleteAllExceptions } from '../../../../../../lists_api_integration/utils'; +import { FtrProviderContext } from '../../../../../ftr_provider_context'; +import { EsArchivePathBuilder } from '../../../../../es_archive_path_builder'; const historicalWindowStart = '2022-10-13T05:00:04.000Z'; const ruleExecutionStart = '2022-10-19T05:00:04.000Z'; -// eslint-disable-next-line import/no-default-export export default ({ getService }: FtrProviderContext) => { const supertest = getService('supertest'); const esArchiver = getService('esArchiver'); @@ -42,7 +41,12 @@ export default ({ getService }: FtrProviderContext) => { index: 'new_terms', log, }); - + // TODO: add a new service + const config = getService('config'); + const ELASTICSEARCH_USERNAME = config.get('servers.kibana.username'); + const isServerless = config.get('serverless'); + const dataPathBuilder = new EsArchivePathBuilder(isServerless); + const path = dataPathBuilder.getPath('auditbeat/hosts'); /** * indexes 2 sets of documents: * - documents in historical window @@ -72,14 +76,14 @@ export default ({ getService }: FtrProviderContext) => { return testId; }; - describe('New terms type rules', () => { + describe('@ess @serverless New terms type rules', () => { before(async () => { - await esArchiver.load('x-pack/test/functional/es_archives/auditbeat/hosts'); + await esArchiver.load(path); await esArchiver.load('x-pack/test/functional/es_archives/security_solution/new_terms'); }); after(async () => { - await esArchiver.unload('x-pack/test/functional/es_archives/auditbeat/hosts'); + await esArchiver.unload(path); await esArchiver.unload('x-pack/test/functional/es_archives/security_solution/new_terms'); await deleteAllAlerts(supertest, log, es); await deleteAllRules(supertest, log); @@ -99,10 +103,10 @@ export default ({ getService }: FtrProviderContext) => { }; const createdRule = await createRule(supertest, log, rule); - const alerts = await getOpenSignals(supertest, log, es, createdRule); + const alerts = await getOpenAlerts(supertest, log, es, createdRule); expect(alerts.hits.hits.length).eql(1); - expect(removeRandomValuedProperties(alerts.hits.hits[0]._source)).eql({ + expect(removeRandomValuedPropertiesFromAlert(alerts.hits.hits[0]._source)).eql({ 'kibana.alert.new_terms': ['zeek-newyork-sha-aa8df15'], 'kibana.alert.rule.category': 'New Terms Rule', 'kibana.alert.rule.consumer': 'siem', @@ -196,7 +200,7 @@ export default ({ getService }: FtrProviderContext) => { }, 'kibana.alert.rule.actions': [], 'kibana.alert.rule.author': [], - 'kibana.alert.rule.created_by': 'elastic', + 'kibana.alert.rule.created_by': ELASTICSEARCH_USERNAME, 'kibana.alert.rule.description': 'Detecting root and admin users', 'kibana.alert.rule.enabled': true, 'kibana.alert.rule.exceptions_list': [], @@ -214,7 +218,7 @@ export default ({ getService }: FtrProviderContext) => { 'kibana.alert.rule.threat': [], 'kibana.alert.rule.to': 'now', 'kibana.alert.rule.type': 'new_terms', - 'kibana.alert.rule.updated_by': 'elastic', + 'kibana.alert.rule.updated_by': ELASTICSEARCH_USERNAME, 'kibana.alert.rule.version': 1, 'kibana.alert.rule.risk_score': 55, 'kibana.alert.rule.severity': 'high', @@ -229,7 +233,7 @@ export default ({ getService }: FtrProviderContext) => { }); }); - it('generates max signals warning when circuit breaker is exceeded', async () => { + it('generates max alerts warning when circuit breaker is exceeded', async () => { const rule: NewTermsRuleCreateProps = { ...getCreateNewTermsRulesSchemaMock('rule-1', true), new_terms_fields: ['process.pid'], @@ -239,10 +243,10 @@ export default ({ getService }: FtrProviderContext) => { }; const { logs } = await previewRule({ supertest, rule }); - expect(logs[0].warnings).contain(getMaxSignalsWarning()); + expect(logs[0].warnings).contain(getMaxAlertsWarning()); }); - it("doesn't generate max signals warning when circuit breaker is met but not exceeded", async () => { + it("doesn't generate max alerts warning when circuit breaker is met but not exceeded", async () => { const rule: NewTermsRuleCreateProps = { ...getCreateNewTermsRulesSchemaMock('rule-1', true), new_terms_fields: ['host.ip'], @@ -252,7 +256,7 @@ export default ({ getService }: FtrProviderContext) => { }; const { logs } = await previewRule({ supertest, rule }); - expect(logs[0].warnings).not.contain(getMaxSignalsWarning()); + expect(logs[0].warnings).not.contain(getMaxAlertsWarning()); }); it('should generate 3 alerts when 1 document has 3 new values', async () => { @@ -990,21 +994,21 @@ export default ({ getService }: FtrProviderContext) => { }); }); - it('should work for max signals > 100', async () => { - const maxSignals = 200; + it('should work for max alerts > 100', async () => { + const maxAlerts = 200; const rule: NewTermsRuleCreateProps = { ...getCreateNewTermsRulesSchemaMock('rule-1', true), new_terms_fields: ['process.pid'], from: '2018-02-19T20:42:00.000Z', // Set the history_window_start close to 'from' so we should alert on all terms in the time range history_window_start: '2018-02-19T20:41:59.000Z', - max_signals: maxSignals, + max_signals: maxAlerts, }; const { previewId } = await previewRule({ supertest, rule }); - const previewAlerts = await getPreviewAlerts({ es, previewId, size: maxSignals * 2 }); + const previewAlerts = await getPreviewAlerts({ es, previewId, size: maxAlerts * 2 }); - expect(previewAlerts.length).eql(maxSignals); + expect(previewAlerts.length).eql(maxAlerts); const processPids = previewAlerts .map((signal) => signal._source?.['kibana.alert.new_terms']) .sort(); diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/rule_execution_logic/non_ecs_fields.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/rule_execution_logic/execution_logic/non_ecs_fields.ts similarity index 96% rename from x-pack/test/detection_engine_api_integration/security_and_spaces/rule_execution_logic/non_ecs_fields.ts rename to x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/rule_execution_logic/execution_logic/non_ecs_fields.ts index 20d2f8e1dc571..e452ffcfaf34e 100644 --- a/x-pack/test/detection_engine_api_integration/security_and_spaces/rule_execution_logic/non_ecs_fields.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/rule_execution_logic/execution_logic/non_ecs_fields.ts @@ -10,18 +10,18 @@ import { deleteAllRules, deleteAllAlerts, getPreviewAlerts, - getRuleForSignalTesting, + getRuleForAlertTesting, previewRule, -} from '../../utils'; -import { dataGeneratorFactory, enhanceDocument } from '../../utils/data_generator'; -import { FtrProviderContext } from '../../common/ftr_provider_context'; + dataGeneratorFactory, + enhanceDocument, +} from '../../../utils'; +import { FtrProviderContext } from '../../../../../ftr_provider_context'; const getQueryRule = (docIdToQuery: string) => ({ - ...getRuleForSignalTesting(['ecs_non_compliant']), + ...getRuleForAlertTesting(['ecs_non_compliant']), query: `id: "${docIdToQuery}"`, }); -// eslint-disable-next-line import/no-default-export export default ({ getService }: FtrProviderContext) => { const supertest = getService('supertest'); const esArchiver = getService('esArchiver'); @@ -56,7 +56,7 @@ export default ({ getService }: FtrProviderContext) => { }; }; - describe('Non ECS fields in alert document source', () => { + describe('@ess @serverless Non ECS fields in alert document source', () => { before(async () => { await esArchiver.load( 'x-pack/test/functional/es_archives/security_solution/ecs_non_compliant' diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/rule_execution_logic/query.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/rule_execution_logic/execution_logic/query.ts similarity index 92% rename from x-pack/test/detection_engine_api_integration/security_and_spaces/rule_execution_logic/query.ts rename to x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/rule_execution_logic/execution_logic/query.ts index 4c38edaf0cd28..a1241c60f5ccf 100644 --- a/x-pack/test/detection_engine_api_integration/security_and_spaces/rule_execution_logic/query.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/rule_execution_logic/execution_logic/query.ts @@ -42,29 +42,32 @@ import { import { DETECTION_ENGINE_RULES_BULK_ACTION, DETECTION_ENGINE_RULES_URL, - DETECTION_ENGINE_SIGNALS_STATUS_URL, + DETECTION_ENGINE_SIGNALS_STATUS_URL as DETECTION_ENGINE_ALERTS_STATUS_URL, } from '@kbn/security-solution-plugin/common/constants'; -import { getMaxSignalsWarning } from '@kbn/security-solution-plugin/server/lib/detection_engine/rule_types/utils/utils'; -import { deleteAllExceptions } from '../../../lists_api_integration/utils'; +import { getMaxSignalsWarning as getMaxAlertsWarning } from '@kbn/security-solution-plugin/server/lib/detection_engine/rule_types/utils/utils'; +import moment from 'moment'; +import { deleteAllExceptions } from '../../../../../../lists_api_integration/utils'; import { createExceptionList, createExceptionListItem, createRule, deleteAllRules, deleteAllAlerts, - getOpenSignals, + getOpenAlerts, getPreviewAlerts, - getRuleForSignalTesting, + getRuleForAlertTesting, getSimpleRule, previewRule, - setSignalStatus, + setAlertStatus, getRuleSOById, + patchRule, createRuleThroughAlertingEndpoint, getRuleSavedObjectWithLegacyInvestigationFields, -} from '../../utils'; -import { FtrProviderContext } from '../../common/ftr_provider_context'; -import { dataGeneratorFactory } from '../../utils/data_generator'; -import { patchRule } from '../../utils/patch_rule'; + dataGeneratorFactory, +} from '../../../utils'; + +import { FtrProviderContext } from '../../../../../ftr_provider_context'; +import { EsArchivePathBuilder } from '../../../../../es_archive_path_builder'; /** * Specific _id to use for some of the tests. If the archiver changes and you see errors @@ -75,22 +78,29 @@ const ID = 'BhbXBmkBR346wHgn4PeZ'; /** * Test coverage: * [x] - Happy path generating 1 alert - * [x] - Rule type respects max signals + * [x] - Rule type respects max alerts * [x] - Alerts on alerts */ -// eslint-disable-next-line import/no-default-export export default ({ getService }: FtrProviderContext) => { const supertest = getService('supertest'); const esArchiver = getService('esArchiver'); const es = getService('es'); const log = getService('log'); const esDeleteAllIndices = getService('esDeleteAllIndices'); + // TODO: add a new service + const config = getService('config'); + const isServerless = config.get('serverless'); + const dataPathBuilder = new EsArchivePathBuilder(isServerless); + const auditbeatPath = dataPathBuilder.getPath('auditbeat/hosts'); - describe('Query type rules', () => { + describe('@ess @serverless Query type rules', () => { before(async () => { - await esArchiver.load('x-pack/test/functional/es_archives/auditbeat/hosts'); - await esArchiver.load('x-pack/test/functional/es_archives/security_solution/alerts/8.1.0'); + await esArchiver.load(auditbeatPath); + await esArchiver.load('x-pack/test/functional/es_archives/security_solution/alerts/8.8.0', { + useCreate: true, + docsOnly: true, + }); await esArchiver.load('x-pack/test/functional/es_archives/signals/severity_risk_overrides'); }); @@ -99,8 +109,7 @@ export default ({ getService }: FtrProviderContext) => { }); after(async () => { - await esArchiver.unload('x-pack/test/functional/es_archives/auditbeat/hosts'); - await esArchiver.unload('x-pack/test/functional/es_archives/security_solution/alerts/8.1.0'); + await esArchiver.unload(auditbeatPath); await esArchiver.unload('x-pack/test/functional/es_archives/signals/severity_risk_overrides'); await deleteAllAlerts(supertest, log, es, ['.preview.alerts-security.alerts-*']); await deleteAllRules(supertest, log); @@ -109,48 +118,48 @@ export default ({ getService }: FtrProviderContext) => { // First test creates a real rule - most remaining tests use preview API it('should have the specific audit record for _id or none of these tests below will pass', async () => { const rule: QueryRuleCreateProps = { - ...getRuleForSignalTesting(['auditbeat-*']), + ...getRuleForAlertTesting(['auditbeat-*']), query: `_id:${ID}`, }; const createdRule = await createRule(supertest, log, rule); - const alerts = await getOpenSignals(supertest, log, es, createdRule); + const alerts = await getOpenAlerts(supertest, log, es, createdRule); expect(alerts.hits.hits.length).greaterThan(0); expect(alerts.hits.hits[0]._source?.['kibana.alert.ancestors'][0].id).eql(ID); }); - it('generates max signals warning when circuit breaker is hit', async () => { + it('generates max alerts warning when circuit breaker is hit', async () => { const rule: QueryRuleCreateProps = { - ...getRuleForSignalTesting(['auditbeat-*']), + ...getRuleForAlertTesting(['auditbeat-*']), }; const { logs } = await previewRule({ supertest, rule }); - expect(logs[0].warnings).contain(getMaxSignalsWarning()); + expect(logs[0].warnings).contain(getMaxAlertsWarning()); }); - it("doesn't generate max signals warning when circuit breaker is met but not exceeded", async () => { + it("doesn't generate max alerts warning when circuit breaker is met but not exceeded", async () => { const rule = { - ...getRuleForSignalTesting(['auditbeat-*']), + ...getRuleForAlertTesting(['auditbeat-*']), query: 'process.executable: "/usr/bin/sudo"', max_signals: 10, }; const { logs } = await previewRule({ supertest, rule }); - expect(logs[0].warnings).not.contain(getMaxSignalsWarning()); + expect(logs[0].warnings).not.contain(getMaxAlertsWarning()); }); it('should abide by max_signals > 100', async () => { - const maxSignals = 200; + const maxAlerts = 200; const rule: QueryRuleCreateProps = { - ...getRuleForSignalTesting(['auditbeat-*']), - max_signals: maxSignals, + ...getRuleForAlertTesting(['auditbeat-*']), + max_signals: maxAlerts, }; const { previewId } = await previewRule({ supertest, rule }); // Search for 2x max_signals to make sure we aren't making more than max_signals - const previewAlerts = await getPreviewAlerts({ es, previewId, size: maxSignals * 2 }); - expect(previewAlerts.length).equal(maxSignals); + const previewAlerts = await getPreviewAlerts({ es, previewId, size: maxAlerts * 2 }); + expect(previewAlerts.length).equal(maxAlerts); }); - it('should have recorded the rule_id within the signal', async () => { + it('should have recorded the rule_id within the alert', async () => { const rule: QueryRuleCreateProps = { - ...getRuleForSignalTesting(['auditbeat-*']), + ...getRuleForAlertTesting(['auditbeat-*']), query: `_id:${ID}`, }; const { previewId } = await previewRule({ supertest, rule }); @@ -158,17 +167,17 @@ export default ({ getService }: FtrProviderContext) => { expect(previewAlerts[0]._source?.[ALERT_RULE_RULE_ID]).eql(getSimpleRule().rule_id); }); - it('should query and get back expected signal structure using a basic KQL query', async () => { + it('should query and get back expected alert structure using a basic KQL query', async () => { const rule: QueryRuleCreateProps = { - ...getRuleForSignalTesting(['auditbeat-*']), + ...getRuleForAlertTesting(['auditbeat-*']), query: `_id:${ID}`, }; const { previewId } = await previewRule({ supertest, rule }); const previewAlerts = await getPreviewAlerts({ es, previewId }); - const signal = previewAlerts[0]._source; + const alert = previewAlerts[0]._source; - expect(signal).eql({ - ...signal, + expect(alert).eql({ + ...alert, [ALERT_ANCESTORS]: [ { id: 'BhbXBmkBR346wHgn4PeZ', @@ -189,11 +198,11 @@ export default ({ getService }: FtrProviderContext) => { }); }); - it('should query and get back expected signal structure when it is a signal on a signal', async () => { - const alertId = '30a75fe46d3dbdfab55982036f77a8d60e2d1112e96f277c3b8c22f9bb57817a'; + it('should query and get back expected alert structure when it is a alert on a alert', async () => { + const alertId = 'eabbdefc23da981f2b74ab58b82622a97bb9878caa11bc914e2adfacc94780f1'; const rule: QueryRuleCreateProps = { - ...getRuleForSignalTesting([`.alerts-security.alerts-default*`]), - rule_id: 'signal-on-signal', + ...getRuleForAlertTesting([`.alerts-security.alerts-default*`]), + rule_id: 'alert-on-alert', query: `_id:${alertId}`, }; @@ -202,43 +211,44 @@ export default ({ getService }: FtrProviderContext) => { expect(previewAlerts.length).to.eql(1); - const signal = previewAlerts[0]._source; + const alert = previewAlerts[0]._source; - if (!signal) { - return expect(signal).to.be.ok(); + if (!alert) { + return expect(alert).to.be.ok(); } - - expect(signal).eql({ - ...signal, - [ALERT_ANCESTORS]: [ - { - id: 'ahEToH8BK09aFtXZFVMq', - type: 'event', - index: 'events-index-000001', - depth: 0, - }, - { - rule: '031d5c00-a72f-11ec-a8a3-7b1c8077fc3e', - id: '30a75fe46d3dbdfab55982036f77a8d60e2d1112e96f277c3b8c22f9bb57817a', - type: 'signal', - index: '.internal.alerts-security.alerts-default-000001', - depth: 1, - }, - ], - [ALERT_WORKFLOW_STATUS]: 'open', - [ALERT_DEPTH]: 2, - [ALERT_ORIGINAL_TIME]: '2022-03-19T02:48:12.634Z', - ...flattenWithPrefix(ALERT_ORIGINAL_EVENT, { - agent_id_status: 'verified', - ingested: '2022-03-19T02:47:57.376Z', - dataset: 'elastic_agent.filebeat', - }), - }); + const date = moment(); + const formattedDate = date.format('YYYY.MM.DD'); + const alertAncestorIndex = isServerless + ? `.ds-.alerts-security.alerts-default-${formattedDate}-000001` + : '.internal.alerts-security.alerts-default-000001'; + expect(alert[ALERT_ANCESTORS]).eql([ + { + id: 'vT9cwocBh3b8EMpD8lsi', + type: 'event', + index: '.ds-logs-endpoint.alerts-default-2023.04.27-000001', + depth: 0, + }, + { + rule: '7015a3e2-e4ea-11ed-8c11-49608884878f', + id: alertId, + type: 'signal', + index: alertAncestorIndex, + depth: 1, + }, + ]); + expect(alert[ALERT_WORKFLOW_STATUS]).eql('open'); + expect(alert[ALERT_DEPTH]).eql(2); + + expect(alert[ALERT_ORIGINAL_TIME]).eql('2023-04-27T11:03:57.906Z'); + expect(alert[`${ALERT_ORIGINAL_EVENT}.agent_id_status`]).eql('auth_metadata_missing'); + expect(alert[`${ALERT_ORIGINAL_EVENT}.ingested`]).eql('2023-04-27T10:58:03Z'); + expect(alert[`${ALERT_ORIGINAL_EVENT}.dataset`]).eql('endpoint'); + expect(alert[`${ALERT_ORIGINAL_EVENT}.ingested`]).eql('2023-04-27T10:58:03Z'); }); it('should not have risk score fields without risk indices', async () => { const rule: QueryRuleCreateProps = { - ...getRuleForSignalTesting(['auditbeat-*']), + ...getRuleForAlertTesting(['auditbeat-*']), query: `_id:${ID}`, }; const { previewId } = await previewRule({ supertest, rule }); @@ -258,7 +268,7 @@ export default ({ getService }: FtrProviderContext) => { it('should have host and user risk score fields', async () => { const rule: QueryRuleCreateProps = { - ...getRuleForSignalTesting(['auditbeat-*']), + ...getRuleForAlertTesting(['auditbeat-*']), query: `_id:${ID}`, }; const { previewId } = await previewRule({ supertest, rule }); @@ -273,11 +283,11 @@ export default ({ getService }: FtrProviderContext) => { /** * Here we test the functionality of Severity and Risk Score overrides (also called "mappings" * in the code). If the rule specifies a mapping, then the final Severity or Risk Score - * value of the signal will be taken from the mapped field of the source event. + * value of the alert will be taken from the mapped field of the source event. */ it('should get default severity and risk score if there is no mapping', async () => { const rule: QueryRuleCreateProps = { - ...getRuleForSignalTesting(['signal_overrides']), + ...getRuleForAlertTesting(['signal_overrides']), severity: 'medium', risk_score: 75, }; @@ -297,7 +307,7 @@ export default ({ getService }: FtrProviderContext) => { it('should get overridden severity if the rule has a mapping for it', async () => { const rule: QueryRuleCreateProps = { - ...getRuleForSignalTesting(['signal_overrides']), + ...getRuleForAlertTesting(['signal_overrides']), severity: 'medium', severity_mapping: [ { field: 'my_severity', operator: 'equals', value: 'sev_900', severity: 'high' }, @@ -334,7 +344,7 @@ export default ({ getService }: FtrProviderContext) => { it('should get overridden risk score if the rule has a mapping for it', async () => { const rule: QueryRuleCreateProps = { - ...getRuleForSignalTesting(['signal_overrides']), + ...getRuleForAlertTesting(['signal_overrides']), severity: 'medium', risk_score: 75, risk_score_mapping: [ @@ -369,7 +379,7 @@ export default ({ getService }: FtrProviderContext) => { it('should get overridden severity and risk score if the rule has both mappings', async () => { const rule: QueryRuleCreateProps = { - ...getRuleForSignalTesting(['signal_overrides']), + ...getRuleForAlertTesting(['signal_overrides']), severity: 'medium', severity_mapping: [ { field: 'my_severity', operator: 'equals', value: 'sev_900', severity: 'high' }, @@ -409,26 +419,26 @@ export default ({ getService }: FtrProviderContext) => { }); }); - it('should generate signals with name_override field', async () => { + it('should generate alerts with name_override field', async () => { const rule: QueryRuleCreateProps = { - ...getRuleForSignalTesting(['auditbeat-*']), + ...getRuleForAlertTesting(['auditbeat-*']), query: `event.action:boot`, rule_name_override: 'event.action', }; const { previewId } = await previewRule({ supertest, rule }); const previewAlerts = await getPreviewAlerts({ es, previewId }); - const fullSignal = previewAlerts[0]; - if (!fullSignal) { - return expect(fullSignal).to.be.ok(); + const fullAlert = previewAlerts[0]; + if (!fullAlert) { + return expect(fullAlert).to.be.ok(); } expect(previewAlerts[0]._source?.['kibana.alert.rule.name']).to.eql('boot'); }); - it('should not generate duplicate signals', async () => { + it('should not generate duplicate alerts', async () => { const rule: QueryRuleCreateProps = { - ...getRuleForSignalTesting(['auditbeat-*']), + ...getRuleForAlertTesting(['auditbeat-*']), query: `_id:${ID}`, }; @@ -448,7 +458,7 @@ export default ({ getService }: FtrProviderContext) => { it('should generate only 1 alert per host name when grouping by host name', async () => { const rule: QueryRuleCreateProps = { - ...getRuleForSignalTesting(['suppression-data']), + ...getRuleForAlertTesting(['suppression-data']), query: `host.name: "host-0"`, alert_suppression: { group_by: ['host.name'], @@ -481,7 +491,7 @@ export default ({ getService }: FtrProviderContext) => { it('should generate multiple alerts when multiple host names are found', async () => { const rule: QueryRuleCreateProps = { - ...getRuleForSignalTesting(['suppression-data']), + ...getRuleForAlertTesting(['suppression-data']), query: `host.name: *`, alert_suppression: { group_by: ['host.name'], @@ -521,7 +531,7 @@ export default ({ getService }: FtrProviderContext) => { it('should generate alerts when using multiple group by fields', async () => { const rule: QueryRuleCreateProps = { - ...getRuleForSignalTesting(['suppression-data']), + ...getRuleForAlertTesting(['suppression-data']), query: `host.name: *`, alert_suppression: { group_by: ['host.name', 'source.ip'], @@ -564,7 +574,7 @@ export default ({ getService }: FtrProviderContext) => { it('should not count documents that were covered by previous alerts', async () => { const rule: QueryRuleCreateProps = { - ...getRuleForSignalTesting(['suppression-data']), + ...getRuleForAlertTesting(['suppression-data']), query: `host.name: *`, alert_suppression: { group_by: ['host.name', 'source.ip'], @@ -632,7 +642,7 @@ export default ({ getService }: FtrProviderContext) => { // so we expect 2 groups to be created from the single document it('should generate multiple alerts for a single doc in multiple groups', async () => { const rule: QueryRuleCreateProps = { - ...getRuleForSignalTesting(['suppression-data']), + ...getRuleForAlertTesting(['suppression-data']), query: `*:*`, alert_suppression: { group_by: ['destination.ip'], @@ -689,7 +699,7 @@ export default ({ getService }: FtrProviderContext) => { // The last alert, with null for destination.ip, should be found by the first rule run but not duplicated // by the second run. const rule: QueryRuleCreateProps = { - ...getRuleForSignalTesting(['suppression-data']), + ...getRuleForAlertTesting(['suppression-data']), query: `*:*`, alert_suppression: { group_by: ['destination.ip'], @@ -760,7 +770,7 @@ export default ({ getService }: FtrProviderContext) => { await indexListOfDocuments([firstDocument, firstDocument]); const rule: QueryRuleCreateProps = { - ...getRuleForSignalTesting(['ecs_compliant']), + ...getRuleForAlertTesting(['ecs_compliant']), rule_id: 'rule-2', query: `id:${id}`, alert_suppression: { @@ -772,7 +782,7 @@ export default ({ getService }: FtrProviderContext) => { }, }; const createdRule = await createRule(supertest, log, rule); - const alerts = await getOpenSignals(supertest, log, es, createdRule); + const alerts = await getOpenAlerts(supertest, log, es, createdRule); expect(alerts.hits.hits.length).eql(1); expect(alerts.hits.hits[0]._source).to.eql({ ...alerts.hits.hits[0]._source, @@ -802,7 +812,7 @@ export default ({ getService }: FtrProviderContext) => { await patchRule(supertest, log, { id: createdRule.id, enabled: false }); await patchRule(supertest, log, { id: createdRule.id, enabled: true }); const afterTimestamp = new Date(); - const secondAlerts = await getOpenSignals( + const secondAlerts = await getOpenAlerts( supertest, log, es, @@ -841,7 +851,7 @@ export default ({ getService }: FtrProviderContext) => { await indexListOfDocuments([firstDocument, firstDocument]); const rule: QueryRuleCreateProps = { - ...getRuleForSignalTesting(['ecs_compliant']), + ...getRuleForAlertTesting(['ecs_compliant']), rule_id: 'rule-2', query: `id:${id}`, alert_suppression: { @@ -853,15 +863,15 @@ export default ({ getService }: FtrProviderContext) => { }, }; const createdRule = await createRule(supertest, log, rule); - const alerts = await getOpenSignals(supertest, log, es, createdRule); + const alerts = await getOpenAlerts(supertest, log, es, createdRule); // Close the alert. Subsequent rule executions should ignore this closed alert // for suppression purposes. const alertIds = alerts.hits.hits.map((alert) => alert._id); await supertest - .post(DETECTION_ENGINE_SIGNALS_STATUS_URL) + .post(DETECTION_ENGINE_ALERTS_STATUS_URL) .set('kbn-xsrf', 'true') - .send(setSignalStatus({ signalIds: alertIds, status: 'closed' })) + .send(setAlertStatus({ alertIds, status: 'closed' })) .expect(200); const secondTimestamp = new Date().toISOString(); @@ -878,7 +888,7 @@ export default ({ getService }: FtrProviderContext) => { await patchRule(supertest, log, { id: createdRule.id, enabled: false }); await patchRule(supertest, log, { id: createdRule.id, enabled: true }); const afterTimestamp = new Date(); - const secondAlerts = await getOpenSignals( + const secondAlerts = await getOpenAlerts( supertest, log, es, @@ -922,7 +932,7 @@ export default ({ getService }: FtrProviderContext) => { it('should generate an alert per rule run when duration is less than rule interval', async () => { const rule: QueryRuleCreateProps = { - ...getRuleForSignalTesting(['suppression-data']), + ...getRuleForAlertTesting(['suppression-data']), query: `host.name: "host-0"`, alert_suppression: { group_by: ['host.name'], @@ -981,7 +991,7 @@ export default ({ getService }: FtrProviderContext) => { it('should update an existing alert in the time window', async () => { const rule: QueryRuleCreateProps = { - ...getRuleForSignalTesting(['suppression-data']), + ...getRuleForAlertTesting(['suppression-data']), query: `host.name: "host-0"`, alert_suppression: { group_by: ['host.name'], @@ -1025,7 +1035,7 @@ export default ({ getService }: FtrProviderContext) => { it('should update the correct alerts based on group_by field-value pair', async () => { const rule: QueryRuleCreateProps = { - ...getRuleForSignalTesting(['suppression-data']), + ...getRuleForAlertTesting(['suppression-data']), query: `host.name: *`, alert_suppression: { group_by: ['host.name'], @@ -1099,7 +1109,7 @@ export default ({ getService }: FtrProviderContext) => { it('should update the correct alerts based on group_by field-value pair even when value is null', async () => { const rule: QueryRuleCreateProps = { - ...getRuleForSignalTesting(['suppression-data']), + ...getRuleForAlertTesting(['suppression-data']), query: `host.name: *`, alert_suppression: { group_by: ['destination.ip'], // Only 1 document populates destination.ip @@ -1162,7 +1172,7 @@ export default ({ getService }: FtrProviderContext) => { await indexListOfDocuments([docWithoutOverride, docWithOverride]); const rule: QueryRuleCreateProps = { - ...getRuleForSignalTesting(['ecs_compliant']), + ...getRuleForAlertTesting(['ecs_compliant']), query: `id:${id}`, alert_suppression: { group_by: ['agent.name'], @@ -1226,7 +1236,7 @@ export default ({ getService }: FtrProviderContext) => { ); const rule: QueryRuleCreateProps = { - ...getRuleForSignalTesting(['ecs_compliant']), + ...getRuleForAlertTesting(['ecs_compliant']), query: `id:${id}`, alert_suppression: { group_by: ['agent.name'], @@ -1313,7 +1323,7 @@ export default ({ getService }: FtrProviderContext) => { await indexListOfDocuments([firstDoc, secondDoc, thirdDoc]); const rule: QueryRuleCreateProps = { - ...getRuleForSignalTesting(['ecs_compliant']), + ...getRuleForAlertTesting(['ecs_compliant']), query: `id:${id}`, alert_suppression: { group_by: ['agent.name'], @@ -1383,7 +1393,7 @@ export default ({ getService }: FtrProviderContext) => { it('should be enriched with host risk score', async () => { const rule: QueryRuleCreateProps = { - ...getRuleForSignalTesting(['suppression-data']), + ...getRuleForAlertTesting(['suppression-data']), query: `host.name: "host-0"`, alert_suppression: { group_by: ['host.name'], @@ -1474,7 +1484,7 @@ export default ({ getService }: FtrProviderContext) => { ]); const rule: QueryRuleCreateProps = { - ...getRuleForSignalTesting(['ecs_compliant']), + ...getRuleForAlertTesting(['ecs_compliant']), query: `id:${id}`, alert_suppression: { group_by: ['agent.name'], @@ -1545,7 +1555,7 @@ export default ({ getService }: FtrProviderContext) => { ]); const rule: QueryRuleCreateProps = { - ...getRuleForSignalTesting(['ecs_compliant']), + ...getRuleForAlertTesting(['ecs_compliant']), query: `id:${id}`, alert_suppression: { group_by: ['agent.name'], @@ -1600,7 +1610,7 @@ export default ({ getService }: FtrProviderContext) => { await indexListOfDocuments([firstDoc, firstDoc]); const rule: QueryRuleCreateProps = { - ...getRuleForSignalTesting(['ecs_compliant']), + ...getRuleForAlertTesting(['ecs_compliant']), query: `id:${id}`, alert_suppression: { group_by: ['agent.name'], @@ -1654,7 +1664,7 @@ export default ({ getService }: FtrProviderContext) => { await indexListOfDocuments([firstDoc, firstDoc]); const rule: QueryRuleCreateProps = { - ...getRuleForSignalTesting(['ecs_compliant']), + ...getRuleForAlertTesting(['ecs_compliant']), query: `id:${id}`, alert_suppression: { group_by: ['agent.name'], @@ -1752,7 +1762,7 @@ export default ({ getService }: FtrProviderContext) => { ]); const rule: QueryRuleCreateProps = { - ...getRuleForSignalTesting(['ecs_compliant']), + ...getRuleForAlertTesting(['ecs_compliant']), query: `id:${id}`, alert_suppression: { group_by: ['agent.name', 'agent.version'], @@ -1831,7 +1841,7 @@ export default ({ getService }: FtrProviderContext) => { ]); const rule: QueryRuleCreateProps = { - ...getRuleForSignalTesting(['ecs_compliant']), + ...getRuleForAlertTesting(['ecs_compliant']), query: `id:${id}`, alert_suppression: { group_by: ['agent.name', 'agent.version'], @@ -1898,7 +1908,7 @@ export default ({ getService }: FtrProviderContext) => { }); it('should create suppressed alerts for single host.name when rule configure with suppress', async () => { const rule: QueryRuleCreateProps = { - ...getRuleForSignalTesting(['ecs_compliant']), + ...getRuleForAlertTesting(['ecs_compliant']), query: `id:${id}`, alert_suppression: { group_by: ['agent.name'], @@ -1965,7 +1975,7 @@ export default ({ getService }: FtrProviderContext) => { it('should create unsuppressed alerts for single host.name', async () => { const rule: QueryRuleCreateProps = { - ...getRuleForSignalTesting(['ecs_compliant']), + ...getRuleForAlertTesting(['ecs_compliant']), query: `id:${id}`, alert_suppression: { group_by: ['agent.name'], @@ -2076,7 +2086,7 @@ export default ({ getService }: FtrProviderContext) => { }); const rule: QueryRuleCreateProps = { - ...getRuleForSignalTesting(['auditbeat-*']), + ...getRuleForAlertTesting(['auditbeat-*']), query: `_id:${ID} or _id:GBbXBmkBR346wHgn5_eR or _id:x10zJ2oE9v5HJNSHhyxi`, exceptions_list: [{ id, list_id: listId, type, namespace_type: namespaceType }], }; @@ -2119,7 +2129,7 @@ export default ({ getService }: FtrProviderContext) => { }); const rule: QueryRuleCreateProps = { - ...getRuleForSignalTesting(['auditbeat-*']), + ...getRuleForAlertTesting(['auditbeat-*']), query: `_id:${ID} or _id:GBbXBmkBR346wHgn5_eR or _id:x10zJ2oE9v5HJNSHhyxi`, exceptions_list: [{ id, list_id: listId, type, namespace_type: namespaceType }], }; @@ -2157,7 +2167,7 @@ export default ({ getService }: FtrProviderContext) => { await indexEnhancedDocuments({ documents: [firstDoc, firstDoc, secondDoc], id }); const rule: QueryRuleCreateProps = { - ...getRuleForSignalTesting(['ecs_compliant']), + ...getRuleForAlertTesting(['ecs_compliant']), query: `id:${id} AND agent.n*: test-1`, from: 'now-1h', interval: '1h', @@ -2188,7 +2198,7 @@ export default ({ getService }: FtrProviderContext) => { await indexEnhancedDocuments({ documents: [firstDoc, firstDoc, secondDoc], id }); const rule: QueryRuleCreateProps = { - ...getRuleForSignalTesting(['ecs_compliant']), + ...getRuleForAlertTesting(['ecs_compliant']), query: `id:${id} AND NOT agent.na*: "test-1"`, from: 'now-1h', interval: '1h', @@ -2215,7 +2225,7 @@ export default ({ getService }: FtrProviderContext) => { await indexEnhancedDocuments({ documents: [firstDoc, secondDoc, thirdDoc], id }); const rule: QueryRuleCreateProps = { - ...getRuleForSignalTesting(['ecs_compliant']), + ...getRuleForAlertTesting(['ecs_compliant']), query: `id:${id} AND agent*: "test-1"`, from: 'now-1h', interval: '1h', @@ -2249,7 +2259,7 @@ export default ({ getService }: FtrProviderContext) => { await indexEnhancedDocuments({ documents: [firstDoc, secondDoc, thirdDoc], id }); const rule: QueryRuleCreateProps = { - ...getRuleForSignalTesting(['ecs_compliant']), + ...getRuleForAlertTesting(['ecs_compliant']), query: `id:${id} AND agent.\\*: test-1`, from: 'now-1h', interval: '1h', @@ -2276,7 +2286,8 @@ export default ({ getService }: FtrProviderContext) => { }); }); - describe('legacy investigation_fields', () => { + // TODO: Ask YARA + describe('@brokenInServerless legacy investigation_fields', () => { let ruleWithLegacyInvestigationField: Rule; beforeEach(async () => { @@ -2317,7 +2328,7 @@ export default ({ getService }: FtrProviderContext) => { .set('elastic-api-version', '2023-10-31') .expect(200); - const alertsAfterEnable = await getOpenSignals(supertest, log, es, ruleBody, 'succeeded'); + const alertsAfterEnable = await getOpenAlerts(supertest, log, es, ruleBody, 'succeeded'); expect(alertsAfterEnable.hits.hits.length > 0).eql(true); }); }); diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/rule_execution_logic/saved_query.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/rule_execution_logic/execution_logic/saved_query.ts similarity index 70% rename from x-pack/test/detection_engine_api_integration/security_and_spaces/rule_execution_logic/saved_query.ts rename to x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/rule_execution_logic/execution_logic/saved_query.ts index ed7173133f9f3..e387a2f840c41 100644 --- a/x-pack/test/detection_engine_api_integration/security_and_spaces/rule_execution_logic/saved_query.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/rule_execution_logic/execution_logic/saved_query.ts @@ -20,10 +20,11 @@ import { createRule, deleteAllRules, deleteAllAlerts, - getOpenSignals, - getRuleForSignalTesting, -} from '../../utils'; -import { FtrProviderContext } from '../../common/ftr_provider_context'; + getOpenAlerts, + getRuleForAlertTesting, +} from '../../../utils'; +import { FtrProviderContext } from '../../../../../ftr_provider_context'; +import { EsArchivePathBuilder } from '../../../../../es_archive_path_builder'; /** * Specific _id to use for some of the tests. If the archiver changes and you see errors @@ -31,37 +32,41 @@ import { FtrProviderContext } from '../../common/ftr_provider_context'; */ const ID = 'BhbXBmkBR346wHgn4PeZ'; -// eslint-disable-next-line import/no-default-export export default ({ getService }: FtrProviderContext) => { const supertest = getService('supertest'); const esArchiver = getService('esArchiver'); const es = getService('es'); const log = getService('log'); + // TODO: add a new service + const config = getService('config'); + const isServerless = config.get('serverless'); + const dataPathBuilder = new EsArchivePathBuilder(isServerless); + const path = dataPathBuilder.getPath('auditbeat/hosts'); - describe('Saved query type rules', () => { + describe('@ess @serverless Saved query type rules', () => { before(async () => { - await esArchiver.load('x-pack/test/functional/es_archives/auditbeat/hosts'); + await esArchiver.load(path); }); after(async () => { - await esArchiver.unload('x-pack/test/functional/es_archives/auditbeat/hosts'); + await esArchiver.unload(path); await deleteAllAlerts(supertest, log, es); await deleteAllRules(supertest, log); }); // First test creates a real rule - remaining tests use preview API - it('should query and get back expected signal structure using a saved query rule', async () => { + it('should query and get back expected alert structure using a saved query rule', async () => { const rule: SavedQueryRuleCreateProps = { - ...getRuleForSignalTesting(['auditbeat-*']), + ...getRuleForAlertTesting(['auditbeat-*']), type: 'saved_query', query: `_id:${ID}`, saved_id: 'doesnt-exist', }; const createdRule = await createRule(supertest, log, rule); - const alerts = await getOpenSignals(supertest, log, es, createdRule); - const signal = alerts.hits.hits[0]._source; - expect(signal).eql({ - ...signal, + const alerts = await getOpenAlerts(supertest, log, es, createdRule); + const alert = alerts.hits.hits[0]._source; + expect(alert).eql({ + ...alert, [ALERT_ANCESTORS]: [ { id: 'BhbXBmkBR346wHgn4PeZ', diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/rule_execution_logic/threat_match.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/rule_execution_logic/execution_logic/threat_match.ts similarity index 91% rename from x-pack/test/detection_engine_api_integration/security_and_spaces/rule_execution_logic/threat_match.ts rename to x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/rule_execution_logic/execution_logic/threat_match.ts index efed9c26375e2..8d7cf8fd9f89b 100644 --- a/x-pack/test/detection_engine_api_integration/security_and_spaces/rule_execution_logic/threat_match.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/rule_execution_logic/execution_logic/threat_match.ts @@ -35,16 +35,18 @@ import { ALERT_ORIGINAL_TIME, } from '@kbn/security-solution-plugin/common/field_maps/field_names'; import { RuleExecutionStatusEnum } from '@kbn/security-solution-plugin/common/api/detection_engine/rule_monitoring'; -import { getMaxSignalsWarning } from '@kbn/security-solution-plugin/server/lib/detection_engine/rule_types/utils/utils'; +import { getMaxSignalsWarning as getMaxAlertsWarning } from '@kbn/security-solution-plugin/server/lib/detection_engine/rule_types/utils/utils'; import { previewRule, - getOpenSignals, + getOpenAlerts, getPreviewAlerts, deleteAllAlerts, deleteAllRules, createRule, -} from '../../utils'; -import { FtrProviderContext } from '../../common/ftr_provider_context'; +} from '../../../utils'; +import { FtrProviderContext } from '../../../../../ftr_provider_context'; +import { EsArchivePathBuilder } from '../../../../../es_archive_path_builder'; + const format = (value: unknown): string => JSON.stringify(value, null, 2); // Asserts that each expected value is included in the subject, independent of @@ -108,8 +110,8 @@ const createThreatMatchRule = ({ threat_index, threat_mapping, threat_filters: [], - threat_indicator_path, ...override, + threat_indicator_path, }); function alertsAreTheSame(alertsA: any[], alertsB: any[]): void { @@ -130,6 +132,7 @@ function alertsAreTheSame(alertsA: any[], alertsB: any[]): void { 'kibana.alert.start', 'kibana.alert.reason', 'kibana.alert.uuid', + 'kibana.alert.url', ]); }; @@ -138,37 +141,40 @@ function alertsAreTheSame(alertsA: any[], alertsB: any[]): void { expect(sort(alertsA.map(mapAlert))).to.eql(sort(alertsB.map(mapAlert))); } - -// eslint-disable-next-line import/no-default-export export default ({ getService }: FtrProviderContext) => { const esArchiver = getService('esArchiver'); const supertest = getService('supertest'); const es = getService('es'); const log = getService('log'); + // TODO: add a new service + const config = getService('config'); + const isServerless = config.get('serverless'); + const ELASTICSEARCH_USERNAME = config.get('servers.kibana.username'); + const dataPathBuilder = new EsArchivePathBuilder(isServerless); + const audibeatHostsPath = dataPathBuilder.getPath('auditbeat/hosts'); + const threatIntelPath = dataPathBuilder.getPath('filebeat/threat_intel'); /** * Specific api integration tests for threat matching rule type */ // FLAKY: https://github.com/elastic/kibana/issues/155304 - describe('Threat match type rules', () => { + describe('@ess @serverless Threat match type rules', () => { before(async () => { - // await deleteSignalsIndex(supertest, log); - // await deleteAllAlerts(supertest, log); - await esArchiver.load('x-pack/test/functional/es_archives/auditbeat/hosts'); + await esArchiver.load(audibeatHostsPath); }); after(async () => { - await esArchiver.unload('x-pack/test/functional/es_archives/auditbeat/hosts'); + await esArchiver.unload(audibeatHostsPath); await deleteAllAlerts(supertest, log, es); await deleteAllRules(supertest, log); }); // First 2 test creates a real rule - remaining tests use preview API - it('should be able to execute and get all signals when doing a specific query (terms query)', async () => { + it('should be able to execute and get all alerts when doing a specific query (terms query)', async () => { const rule: ThreatMatchRuleCreateProps = createThreatMatchRule(); const createdRule = await createRule(supertest, log, rule); - const alerts = await getOpenSignals( + const alerts = await getOpenAlerts( supertest, log, es, @@ -178,16 +184,15 @@ export default ({ getService }: FtrProviderContext) => { ); expect(alerts.hits.hits.length).equal(88); const fullSource = alerts.hits.hits.find( - (signal) => - (signal._source?.[ALERT_ANCESTORS] as Ancestor[])[0].id === '7yJ-B2kBR346wHgnhlMn' + (alert) => (alert._source?.[ALERT_ANCESTORS] as Ancestor[])[0].id === '7yJ-B2kBR346wHgnhlMn' ); - const fullSignal = fullSource?._source; - if (!fullSignal) { - return expect(fullSignal).to.be.ok(); + const fullAlert = fullSource?._source; + if (!fullAlert) { + return expect(fullAlert).to.be.ok(); } - expect(fullSignal).eql({ - ...fullSignal, - '@timestamp': fullSignal['@timestamp'], + expect(fullAlert).eql({ + ...fullAlert, + '@timestamp': fullAlert['@timestamp'], agent: { ephemeral_id: '1b4978a0-48be-49b1-ac96-323425b389ab', hostname: 'zeek-sensor-amsterdam', @@ -281,25 +286,25 @@ export default ({ getService }: FtrProviderContext) => { [ALERT_ORIGINAL_EVENT_ACTION]: 'error', [ALERT_ORIGINAL_EVENT_CATEGORY]: 'user-login', [ALERT_ORIGINAL_EVENT_MODULE]: 'auditd', - [ALERT_ORIGINAL_TIME]: fullSignal[ALERT_ORIGINAL_TIME], + [ALERT_ORIGINAL_TIME]: fullAlert[ALERT_ORIGINAL_TIME], [ALERT_REASON]: 'user-login event with source 46.101.47.213 by root on zeek-sensor-amsterdam created high alert Query with a rule id.', - [ALERT_RULE_UUID]: fullSignal[ALERT_RULE_UUID], + [ALERT_RULE_UUID]: fullAlert[ALERT_RULE_UUID], [ALERT_STATUS]: 'active', - [ALERT_UUID]: fullSignal[ALERT_UUID], + [ALERT_UUID]: fullAlert[ALERT_UUID], [ALERT_WORKFLOW_STATUS]: 'open', [ALERT_WORKFLOW_TAGS]: [], [SPACE_IDS]: ['default'], - [VERSION]: fullSignal[VERSION], + [VERSION]: fullAlert[VERSION], threat: { - enrichments: get(fullSignal, 'threat.enrichments'), + enrichments: get(fullAlert, 'threat.enrichments'), }, ...flattenWithPrefix(ALERT_RULE_NAMESPACE, { actions: [], author: [], category: 'Indicator Match Rule', consumer: 'siem', - created_by: 'elastic', + created_by: ELASTICSEARCH_USERNAME, description: 'Detecting root and admin users', enabled: true, exceptions_list: [], @@ -320,14 +325,14 @@ export default ({ getService }: FtrProviderContext) => { threat: [], to: 'now', type: 'threat_match', - updated_at: fullSignal[ALERT_RULE_UPDATED_AT], - updated_by: 'elastic', - uuid: fullSignal[ALERT_RULE_UUID], + updated_at: fullAlert[ALERT_RULE_UPDATED_AT], + updated_by: ELASTICSEARCH_USERNAME, + uuid: fullAlert[ALERT_RULE_UUID], version: 1, }), }); }); - it('should be able to execute and get all signals when doing a specific query (match query)', async () => { + it('should be able to execute and get all alerts when doing a specific query (match query)', async () => { const rule: ThreatMatchRuleCreateProps = createThreatMatchRule({ threat_mapping: [ // We match host.name against host.name @@ -349,7 +354,7 @@ export default ({ getService }: FtrProviderContext) => { }); const createdRule = await createRule(supertest, log, rule); - const alerts = await getOpenSignals( + const alerts = await getOpenAlerts( supertest, log, es, @@ -359,16 +364,15 @@ export default ({ getService }: FtrProviderContext) => { ); expect(alerts.hits.hits.length).equal(88); const fullSource = alerts.hits.hits.find( - (signal) => - (signal._source?.[ALERT_ANCESTORS] as Ancestor[])[0].id === '7yJ-B2kBR346wHgnhlMn' + (alert) => (alert._source?.[ALERT_ANCESTORS] as Ancestor[])[0].id === '7yJ-B2kBR346wHgnhlMn' ); - const fullSignal = fullSource?._source; - if (!fullSignal) { - return expect(fullSignal).to.be.ok(); + const fullAlert = fullSource?._source; + if (!fullAlert) { + return expect(fullAlert).to.be.ok(); } - expect(fullSignal).eql({ - ...fullSignal, - '@timestamp': fullSignal['@timestamp'], + expect(fullAlert).eql({ + ...fullAlert, + '@timestamp': fullAlert['@timestamp'], agent: { ephemeral_id: '1b4978a0-48be-49b1-ac96-323425b389ab', hostname: 'zeek-sensor-amsterdam', @@ -462,24 +466,24 @@ export default ({ getService }: FtrProviderContext) => { [ALERT_ORIGINAL_EVENT_ACTION]: 'error', [ALERT_ORIGINAL_EVENT_CATEGORY]: 'user-login', [ALERT_ORIGINAL_EVENT_MODULE]: 'auditd', - [ALERT_ORIGINAL_TIME]: fullSignal[ALERT_ORIGINAL_TIME], + [ALERT_ORIGINAL_TIME]: fullAlert[ALERT_ORIGINAL_TIME], [ALERT_REASON]: 'user-login event with source 46.101.47.213 by root on zeek-sensor-amsterdam created high alert Query with a rule id.', - [ALERT_RULE_UUID]: fullSignal[ALERT_RULE_UUID], + [ALERT_RULE_UUID]: fullAlert[ALERT_RULE_UUID], [ALERT_STATUS]: 'active', - [ALERT_UUID]: fullSignal[ALERT_UUID], + [ALERT_UUID]: fullAlert[ALERT_UUID], [ALERT_WORKFLOW_STATUS]: 'open', [SPACE_IDS]: ['default'], - [VERSION]: fullSignal[VERSION], + [VERSION]: fullAlert[VERSION], threat: { - enrichments: get(fullSignal, 'threat.enrichments'), + enrichments: get(fullAlert, 'threat.enrichments'), }, ...flattenWithPrefix(ALERT_RULE_NAMESPACE, { actions: [], author: [], category: 'Indicator Match Rule', consumer: 'siem', - created_by: 'elastic', + created_by: ELASTICSEARCH_USERNAME, description: 'Detecting root and admin users', enabled: true, exceptions_list: [], @@ -500,18 +504,18 @@ export default ({ getService }: FtrProviderContext) => { threat: [], to: 'now', type: 'threat_match', - updated_at: fullSignal[ALERT_RULE_UPDATED_AT], - updated_by: 'elastic', - uuid: fullSignal[ALERT_RULE_UUID], + updated_at: fullAlert[ALERT_RULE_UPDATED_AT], + updated_by: ELASTICSEARCH_USERNAME, + uuid: fullAlert[ALERT_RULE_UUID], version: 1, }), }); }); - it('generates max signals warning when circuit breaker is hit', async () => { + it('generates max alerts warning when circuit breaker is hit', async () => { const rule: ThreatMatchRuleCreateProps = { ...createThreatMatchRule(), max_signals: 87 }; // Query generates 88 alerts with current esArchive const { logs } = await previewRule({ supertest, rule }); - expect(logs[0].warnings).contain(getMaxSignalsWarning()); + expect(logs[0].warnings).contain(getMaxAlertsWarning()); }); it('terms and match should have the same alerts with pagination', async () => { @@ -552,7 +556,7 @@ export default ({ getService }: FtrProviderContext) => { const createdRuleTerm = await createRule(supertest, log, termRule); const createdRuleMatch = await createRule(supertest, log, matchRule); - const alertsTerm = await getOpenSignals( + const alertsTerm = await getOpenAlerts( supertest, log, es, @@ -560,7 +564,7 @@ export default ({ getService }: FtrProviderContext) => { RuleExecutionStatusEnum.succeeded, 100 ); - const alertsMatch = await getOpenSignals( + const alertsMatch = await getOpenAlerts( supertest, log, es, @@ -593,7 +597,7 @@ export default ({ getService }: FtrProviderContext) => { expect(previewAlerts.length).equal(0); }); - it('should return 0 signals when using an AND and one of the clauses does not have data', async () => { + it('should return 0 alerts when using an AND and one of the clauses does not have data', async () => { const rule: ThreatMatchRuleCreateProps = createThreatMatchRule({ threat_mapping: [ { @@ -618,7 +622,7 @@ export default ({ getService }: FtrProviderContext) => { expect(previewAlerts.length).equal(0); }); - it('should return 0 signals when using an AND and one of the clauses has a made up value that does not exist', async () => { + it('should return 0 alerts when using an AND and one of the clauses has a made up value that does not exist', async () => { const rule: ThreatMatchRuleCreateProps = createThreatMatchRule({ threat_mapping: [ { @@ -661,14 +665,14 @@ export default ({ getService }: FtrProviderContext) => { describe('indicator enrichment: threat-first search', () => { before(async () => { - await esArchiver.load('x-pack/test/functional/es_archives/filebeat/threat_intel'); + await esArchiver.load(threatIntelPath); }); after(async () => { - await esArchiver.unload('x-pack/test/functional/es_archives/filebeat/threat_intel'); + await esArchiver.unload(threatIntelPath); }); - it('enriches signals with the single indicator that matched', async () => { + it('enriches alerts with the single indicator that matched', async () => { const rule: ThreatMatchRuleCreateProps = createThreatMatchRule({ threat_mapping: [ { @@ -744,9 +748,9 @@ export default ({ getService }: FtrProviderContext) => { ]); }); - it('enriches signals with multiple indicators if several matched', async () => { + it('enriches alerts with multiple indicators if several matched', async () => { const rule: ThreatMatchRuleCreateProps = createThreatMatchRule({ - query: 'NOT source.port:35326', // specify query to have signals more than treat indicators, but only 1 will match + query: 'NOT source.port:35326', // specify query to have alerts more than treat indicators, but only 1 will match threat_query: 'threat.indicator.ip: *', threat_index: ['filebeat-*'], // Mimics indicators from the filebeat MISP module threat_mapping: [ @@ -811,7 +815,7 @@ export default ({ getService }: FtrProviderContext) => { it('adds a single indicator that matched multiple fields', async () => { const rule: ThreatMatchRuleCreateProps = createThreatMatchRule({ - query: 'NOT source.port:35326', // specify query to have signals more than treat indicators, but only 1 will match + query: 'NOT source.port:35326', // specify query to have alerts more than treat indicators, but only 1 will match threat_query: 'threat.indicator.port: 57324 or threat.indicator.ip:45.115.45.3', // narrow our query to a single indicator threat_index: ['filebeat-*'], // Mimics indicators from the filebeat MISP module threat_mapping: [ @@ -907,7 +911,7 @@ export default ({ getService }: FtrProviderContext) => { ]); }); - it('generates multiple signals with multiple matches', async () => { + it('generates multiple alerts with multiple matches', async () => { const rule: ThreatMatchRuleCreateProps = createThreatMatchRule({ threat_query: '*:*', threat_index: ['filebeat-*'], // Mimics indicators from the filebeat MISP module @@ -1032,7 +1036,7 @@ export default ({ getService }: FtrProviderContext) => { }); // https://github.com/elastic/kibana/issues/149920 - // generates same number of alerts similarly to "enriches signals with the single indicator that matches" test + // generates same number of alerts similarly to "enriches alerts with the single indicator that matches" test it('generates alerts with single match if queries contain field path wildcards', async () => { const rule: ThreatMatchRuleCreateProps = createThreatMatchRule({ // still matches all documents as default *:* @@ -1060,14 +1064,14 @@ export default ({ getService }: FtrProviderContext) => { describe('indicator enrichment: event-first search', () => { before(async () => { - await esArchiver.load('x-pack/test/functional/es_archives/filebeat/threat_intel'); + await esArchiver.load(threatIntelPath); }); after(async () => { - await esArchiver.unload('x-pack/test/functional/es_archives/filebeat/threat_intel'); + await esArchiver.unload(threatIntelPath); }); - it('enriches signals with the single indicator that matched', async () => { + it('enriches alerts with the single indicator that matched', async () => { const termRule: ThreatMatchRuleCreateProps = createThreatMatchRule({ query: 'destination.ip:159.89.119.67', threat_query: 'threat.indicator.domain: *', // narrow things down to indicators with a domain @@ -1168,7 +1172,7 @@ export default ({ getService }: FtrProviderContext) => { alertsAreTheSame(termPreviewAlerts, matchPrevieAlerts); }); - it('enriches signals with multiple indicators if several matched', async () => { + it('enriches alerts with multiple indicators if several matched', async () => { const termRule: ThreatMatchRuleCreateProps = createThreatMatchRule({ query: 'source.port: 57324', // narrow our query to a single record that matches two indicatorsthreat_query: 'threat.indicator.ip: *', threat_query: 'threat.indicator.ip: *', @@ -1408,7 +1412,7 @@ export default ({ getService }: FtrProviderContext) => { ); }); - it('generates multiple signals with multiple matches', async () => { + it('generates multiple alerts with multiple matches', async () => { const rule: ThreatMatchRuleCreateProps = createThreatMatchRule({ query: '(source.port:57324 and source.ip:45.115.45.3) or destination.ip:159.89.119.67', // narrow our query to a single record that matches two indicators threat_query: '*:*', @@ -1534,7 +1538,7 @@ export default ({ getService }: FtrProviderContext) => { }); // https://github.com/elastic/kibana/issues/149920 - // creates same number of alerts similarly to "generates multiple signals with multiple matches" test + // creates same number of alerts similarly to "generates multiple alerts with multiple matches" test it('generates alerts with multiple matches if queries contain field path wildcards', async () => { const rule: ThreatMatchRuleCreateProps = createThreatMatchRule({ // source.po* matches port source.port field @@ -1605,16 +1609,16 @@ export default ({ getService }: FtrProviderContext) => { const previewAlerts = await getPreviewAlerts({ es, previewId, size: 100 }); expect(previewAlerts.length).equal(88); const fullSource = previewAlerts.find( - (signal) => - (signal._source?.[ALERT_ANCESTORS] as Ancestor[])[0].id === '7yJ-B2kBR346wHgnhlMn' + (alert) => + (alert._source?.[ALERT_ANCESTORS] as Ancestor[])[0].id === '7yJ-B2kBR346wHgnhlMn' ); - const fullSignal = fullSource?._source; - if (!fullSignal) { - return expect(fullSignal).to.be.ok(); + const fullAlert = fullSource?._source; + if (!fullAlert) { + return expect(fullAlert).to.be.ok(); } - expect(fullSignal?.host?.risk?.calculated_level).to.eql('Critical'); - expect(fullSignal?.host?.risk?.calculated_score_norm).to.eql(70); + expect(fullAlert?.host?.risk?.calculated_level).to.eql('Critical'); + expect(fullAlert?.host?.risk?.calculated_score_norm).to.eql(70); }); }); }); diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/rule_execution_logic/threshold.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/rule_execution_logic/execution_logic/threshold.ts similarity index 73% rename from x-pack/test/detection_engine_api_integration/security_and_spaces/rule_execution_logic/threshold.ts rename to x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/rule_execution_logic/execution_logic/threshold.ts index 36f41da15e1ee..81203c3d48a28 100644 --- a/x-pack/test/detection_engine_api_integration/security_and_spaces/rule_execution_logic/threshold.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/rule_execution_logic/execution_logic/threshold.ts @@ -21,51 +21,56 @@ import { ALERT_ORIGINAL_TIME, ALERT_THRESHOLD_RESULT, } from '@kbn/security-solution-plugin/common/field_maps/field_names'; -import { getMaxSignalsWarning } from '@kbn/security-solution-plugin/server/lib/detection_engine/rule_types/utils/utils'; +import { getMaxSignalsWarning as getMaxAlertsWarning } from '@kbn/security-solution-plugin/server/lib/detection_engine/rule_types/utils/utils'; import { createRule, - getOpenSignals, + getOpenAlerts, getPreviewAlerts, - getThresholdRuleForSignalTesting, + getThresholdRuleForAlertTesting, previewRule, -} from '../../utils'; -import { FtrProviderContext } from '../../common/ftr_provider_context'; +} from '../../../utils'; +import { FtrProviderContext } from '../../../../../ftr_provider_context'; +import { EsArchivePathBuilder } from '../../../../../es_archive_path_builder'; -// eslint-disable-next-line import/no-default-export export default ({ getService }: FtrProviderContext) => { const supertest = getService('supertest'); const esArchiver = getService('esArchiver'); const es = getService('es'); const log = getService('log'); + // TODO: add a new service + const config = getService('config'); + const isServerless = config.get('serverless'); + const dataPathBuilder = new EsArchivePathBuilder(isServerless); + const path = dataPathBuilder.getPath('auditbeat/hosts'); - describe('Threshold type rules', () => { + describe('@ess @serverless Threshold type rules', () => { before(async () => { - await esArchiver.load('x-pack/test/functional/es_archives/auditbeat/hosts'); + await esArchiver.load(path); }); after(async () => { - await esArchiver.unload('x-pack/test/functional/es_archives/auditbeat/hosts'); + await esArchiver.unload(path); }); // First test creates a real rule - remaining tests use preview API - it('generates 1 signal from Threshold rules when threshold is met', async () => { + it('generates 1 alert from Threshold rules when threshold is met', async () => { const rule: ThresholdRuleCreateProps = { - ...getThresholdRuleForSignalTesting(['auditbeat-*']), + ...getThresholdRuleForAlertTesting(['auditbeat-*']), threshold: { field: ['host.id'], value: 700, }, }; const createdRule = await createRule(supertest, log, rule); - const alerts = await getOpenSignals(supertest, log, es, createdRule); + const alerts = await getOpenAlerts(supertest, log, es, createdRule); expect(alerts.hits.hits.length).eql(1); - const fullSignal = alerts.hits.hits[0]._source; - if (!fullSignal) { - return expect(fullSignal).to.be.ok(); + const fullAlert = alerts.hits.hits[0]._source; + if (!fullAlert) { + return expect(fullAlert).to.be.ok(); } - const eventIds = (fullSignal?.[ALERT_ANCESTORS] as Ancestor[]).map((event) => event.id); - expect(fullSignal).eql({ - ...fullSignal, + const eventIds = (fullAlert?.[ALERT_ANCESTORS] as Ancestor[]).map((event) => event.id); + expect(fullAlert).eql({ + ...fullAlert, 'host.id': '8cc95778cce5407c809480e8e32ad76b', [EVENT_KIND]: 'signal', [ALERT_ANCESTORS]: [ @@ -77,9 +82,9 @@ export default ({ getService }: FtrProviderContext) => { }, ], [ALERT_WORKFLOW_STATUS]: 'open', - [ALERT_REASON]: 'event created high alert Signal Testing Query.', - [ALERT_RULE_UUID]: fullSignal[ALERT_RULE_UUID], - [ALERT_ORIGINAL_TIME]: fullSignal[ALERT_ORIGINAL_TIME], + [ALERT_REASON]: 'event created high alert Alert Testing Query.', + [ALERT_RULE_UUID]: fullAlert[ALERT_RULE_UUID], + [ALERT_ORIGINAL_TIME]: fullAlert[ALERT_ORIGINAL_TIME], [ALERT_DEPTH]: 1, [ALERT_THRESHOLD_RESULT]: { terms: [ @@ -94,9 +99,9 @@ export default ({ getService }: FtrProviderContext) => { }); }); - it('generates max signals warning when circuit breaker is exceeded', async () => { + it('generates max alerts warning when circuit breaker is exceeded', async () => { const rule: ThresholdRuleCreateProps = { - ...getThresholdRuleForSignalTesting(['auditbeat-*']), + ...getThresholdRuleForAlertTesting(['auditbeat-*']), threshold: { field: 'host.id', value: 1, // This value generates 7 alerts with the current esArchive @@ -104,12 +109,12 @@ export default ({ getService }: FtrProviderContext) => { max_signals: 5, }; const { logs } = await previewRule({ supertest, rule }); - expect(logs[0].warnings).contain(getMaxSignalsWarning()); + expect(logs[0].warnings).contain(getMaxAlertsWarning()); }); - it("doesn't generate max signals warning when circuit breaker is met but not exceeded", async () => { + it("doesn't generate max alerts warning when circuit breaker is met but not exceeded", async () => { const rule: ThresholdRuleCreateProps = { - ...getThresholdRuleForSignalTesting(['auditbeat-*']), + ...getThresholdRuleForAlertTesting(['auditbeat-*']), threshold: { field: 'host.id', value: 1, // This value generates 7 alerts with the current esArchive @@ -117,12 +122,12 @@ export default ({ getService }: FtrProviderContext) => { max_signals: 7, }; const { logs } = await previewRule({ supertest, rule }); - expect(logs[0].warnings).not.contain(getMaxSignalsWarning()); + expect(logs[0].warnings).not.contain(getMaxAlertsWarning()); }); - it('generates 2 signals from Threshold rules when threshold is met', async () => { + it('generates 2 alerts from Threshold rules when threshold is met', async () => { const rule: ThresholdRuleCreateProps = { - ...getThresholdRuleForSignalTesting(['auditbeat-*']), + ...getThresholdRuleForAlertTesting(['auditbeat-*']), threshold: { field: 'host.id', value: 100, @@ -135,7 +140,7 @@ export default ({ getService }: FtrProviderContext) => { it('applies the provided query before bucketing ', async () => { const rule: ThresholdRuleCreateProps = { - ...getThresholdRuleForSignalTesting(['auditbeat-*']), + ...getThresholdRuleForAlertTesting(['auditbeat-*']), query: 'host.id:"2ab45fc1c41e4c84bbd02202a7e5761f"', threshold: { field: 'process.name', @@ -147,9 +152,9 @@ export default ({ getService }: FtrProviderContext) => { expect(previewAlerts.length).eql(1); }); - it('generates no signals from Threshold rules when threshold is met and cardinality is not met', async () => { + it('generates no alerts from Threshold rules when threshold is met and cardinality is not met', async () => { const rule: ThresholdRuleCreateProps = { - ...getThresholdRuleForSignalTesting(['auditbeat-*']), + ...getThresholdRuleForAlertTesting(['auditbeat-*']), threshold: { field: 'host.id', value: 100, @@ -166,9 +171,9 @@ export default ({ getService }: FtrProviderContext) => { expect(previewAlerts.length).eql(0); }); - it('generates no signals from Threshold rules when cardinality is met and threshold is not met', async () => { + it('generates no alerts from Threshold rules when cardinality is met and threshold is not met', async () => { const rule: ThresholdRuleCreateProps = { - ...getThresholdRuleForSignalTesting(['auditbeat-*']), + ...getThresholdRuleForAlertTesting(['auditbeat-*']), threshold: { field: 'host.id', value: 1000, @@ -185,9 +190,9 @@ export default ({ getService }: FtrProviderContext) => { expect(previewAlerts.length).eql(0); }); - it('generates signals from Threshold rules when threshold and cardinality are both met', async () => { + it('generates alerts from Threshold rules when threshold and cardinality are both met', async () => { const rule: ThresholdRuleCreateProps = { - ...getThresholdRuleForSignalTesting(['auditbeat-*']), + ...getThresholdRuleForAlertTesting(['auditbeat-*']), threshold: { field: 'host.id', value: 100, @@ -202,13 +207,13 @@ export default ({ getService }: FtrProviderContext) => { const { previewId } = await previewRule({ supertest, rule }); const previewAlerts = await getPreviewAlerts({ es, previewId }); expect(previewAlerts.length).eql(1); - const fullSignal = previewAlerts[0]._source; - if (!fullSignal) { - return expect(fullSignal).to.be.ok(); + const fullAlert = previewAlerts[0]._source; + if (!fullAlert) { + return expect(fullAlert).to.be.ok(); } - const eventIds = (fullSignal?.[ALERT_ANCESTORS] as Ancestor[]).map((event) => event.id); - expect(fullSignal).eql({ - ...fullSignal, + const eventIds = (fullAlert?.[ALERT_ANCESTORS] as Ancestor[]).map((event) => event.id); + expect(fullAlert).eql({ + ...fullAlert, 'host.id': '8cc95778cce5407c809480e8e32ad76b', [EVENT_KIND]: 'signal', [ALERT_ANCESTORS]: [ @@ -220,9 +225,9 @@ export default ({ getService }: FtrProviderContext) => { }, ], [ALERT_WORKFLOW_STATUS]: 'open', - [ALERT_REASON]: `event created high alert Signal Testing Query.`, - [ALERT_RULE_UUID]: fullSignal[ALERT_RULE_UUID], - [ALERT_ORIGINAL_TIME]: fullSignal[ALERT_ORIGINAL_TIME], + [ALERT_REASON]: `event created high alert Alert Testing Query.`, + [ALERT_RULE_UUID]: fullAlert[ALERT_RULE_UUID], + [ALERT_ORIGINAL_TIME]: fullAlert[ALERT_ORIGINAL_TIME], [ALERT_DEPTH]: 1, [ALERT_THRESHOLD_RESULT]: { terms: [ @@ -243,9 +248,9 @@ export default ({ getService }: FtrProviderContext) => { }); }); - it('should not generate signals if only one field meets the threshold requirement', async () => { + it('should not generate alerts if only one field meets the threshold requirement', async () => { const rule: ThresholdRuleCreateProps = { - ...getThresholdRuleForSignalTesting(['auditbeat-*']), + ...getThresholdRuleForAlertTesting(['auditbeat-*']), threshold: { field: ['host.id', 'process.name'], value: 22, @@ -256,9 +261,9 @@ export default ({ getService }: FtrProviderContext) => { expect(previewAlerts.length).eql(0); }); - it('generates signals from Threshold rules when bucketing by multiple fields', async () => { + it('generates alerts from Threshold rules when bucketing by multiple fields', async () => { const rule: ThresholdRuleCreateProps = { - ...getThresholdRuleForSignalTesting(['auditbeat-*']), + ...getThresholdRuleForAlertTesting(['auditbeat-*']), threshold: { field: ['host.id', 'process.name', 'event.module'], value: 21, @@ -267,13 +272,13 @@ export default ({ getService }: FtrProviderContext) => { const { previewId } = await previewRule({ supertest, rule }); const previewAlerts = await getPreviewAlerts({ es, previewId }); expect(previewAlerts.length).eql(1); - const fullSignal = previewAlerts[0]._source; - if (!fullSignal) { - return expect(fullSignal).to.be.ok(); + const fullAlert = previewAlerts[0]._source; + if (!fullAlert) { + return expect(fullAlert).to.be.ok(); } - const eventIds = (fullSignal[ALERT_ANCESTORS] as Ancestor[]).map((event) => event.id); - expect(fullSignal).eql({ - ...fullSignal, + const eventIds = (fullAlert[ALERT_ANCESTORS] as Ancestor[]).map((event) => event.id); + expect(fullAlert).eql({ + ...fullAlert, 'event.module': 'system', 'host.id': '2ab45fc1c41e4c84bbd02202a7e5761f', 'process.name': 'sshd', @@ -287,9 +292,9 @@ export default ({ getService }: FtrProviderContext) => { }, ], [ALERT_WORKFLOW_STATUS]: 'open', - [ALERT_REASON]: `event with process sshd, created high alert Signal Testing Query.`, - [ALERT_RULE_UUID]: fullSignal[ALERT_RULE_UUID], - [ALERT_ORIGINAL_TIME]: fullSignal[ALERT_ORIGINAL_TIME], + [ALERT_REASON]: `event with process sshd, created high alert Alert Testing Query.`, + [ALERT_RULE_UUID]: fullAlert[ALERT_RULE_UUID], + [ALERT_ORIGINAL_TIME]: fullAlert[ALERT_ORIGINAL_TIME], [ALERT_DEPTH]: 1, [ALERT_THRESHOLD_RESULT]: { terms: [ @@ -315,15 +320,15 @@ export default ({ getService }: FtrProviderContext) => { // https://github.com/elastic/kibana/issues/149920 it('generates 1 alert when threshold is met and rule query has wildcard in field name', async () => { const rule: ThresholdRuleCreateProps = { - ...getThresholdRuleForSignalTesting(['auditbeat-*']), - query: 'agent.ty*:auditbeat', // this query should match all documents from index and we will receive 1 alert, similarly to "generates 1 signal from Threshold rules when threshold is met" test case + ...getThresholdRuleForAlertTesting(['auditbeat-*']), + query: 'agent.ty*:auditbeat', // this query should match all documents from index and we will receive 1 alert, similarly to "generates 1 alert from Threshold rules when threshold is met" test case threshold: { field: ['host.id'], value: 700, }, }; const createdRule = await createRule(supertest, log, rule); - const alerts = await getOpenSignals(supertest, log, es, createdRule); + const alerts = await getOpenAlerts(supertest, log, es, createdRule); expect(alerts.hits.hits.length).eql(1); }); @@ -342,7 +347,7 @@ export default ({ getService }: FtrProviderContext) => { it('applies timestamp override when using single field', async () => { const rule: ThresholdRuleCreateProps = { - ...getThresholdRuleForSignalTesting(['timestamp-fallback-test']), + ...getThresholdRuleForAlertTesting(['timestamp-fallback-test']), threshold: { field: 'host.name', value: 1, @@ -370,7 +375,7 @@ export default ({ getService }: FtrProviderContext) => { it('applies timestamp override when using multiple fields', async () => { const rule: ThresholdRuleCreateProps = { - ...getThresholdRuleForSignalTesting(['timestamp-fallback-test']), + ...getThresholdRuleForAlertTesting(['timestamp-fallback-test']), threshold: { field: ['host.name', 'source.ip'], value: 1, @@ -408,7 +413,7 @@ export default ({ getService }: FtrProviderContext) => { it('should be enriched with host risk score', async () => { const rule: ThresholdRuleCreateProps = { - ...getThresholdRuleForSignalTesting(['auditbeat-*']), + ...getThresholdRuleForAlertTesting(['auditbeat-*']), threshold: { field: 'host.name', value: 100, diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/group10/ignore_fields.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/rule_execution_logic/ignore_fields.ts similarity index 70% rename from x-pack/test/detection_engine_api_integration/security_and_spaces/group10/ignore_fields.ts rename to x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/rule_execution_logic/ignore_fields.ts index 829224b9c6089..6ddee1846067d 100644 --- a/x-pack/test/detection_engine_api_integration/security_and_spaces/group10/ignore_fields.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/rule_execution_logic/ignore_fields.ts @@ -7,16 +7,15 @@ import expect from '@kbn/expect'; -import { FtrProviderContext } from '../../../common/ftr_provider_context'; import { createRule, - createSignalsIndex, + createAlertsIndex, deleteAllRules, deleteAllAlerts, - getEqlRuleForSignalTesting, - getSignalsById, + getEqlRuleForAlertTesting, + getAlertsById, waitForRuleSuccess, - waitForSignalsToBePresent, + waitForAlertsToBePresent, } from '../../utils'; interface Ignore { @@ -26,10 +25,10 @@ interface Ignore { testing_regex?: string; } -// eslint-disable-next-line import/no-default-export +import { FtrProviderContext } from '../../../../ftr_provider_context'; export default ({ getService }: FtrProviderContext): void => { /** - * See the config file (detection_engine_api_integration/common/config.ts) for which field values were added to be ignored + * See the config file (config.ts) for which field values were added to be ignored * for testing. The values should be in the config around the area of: * --xpack.securitySolution.alertIgnoreFields=[testing.ignore_1,/[testingRegex] * meaning that the ignore fields values should be the array: ["testing.ignore_1", "/[testingRegex]/"] @@ -47,7 +46,7 @@ export default ({ getService }: FtrProviderContext): void => { * server/lib/detection_engine/signals/source_fields_merging/utils/is_ignored.ts * server/lib/detection_engine/signals/source_fields_merging/utils/is_eql_bug_77152.ts */ - describe('ignore_fields', () => { + describe('@ess @serverless ignore_fields', () => { const supertest = getService('supertest'); const esArchiver = getService('esArchiver'); const log = getService('log'); @@ -62,7 +61,7 @@ export default ({ getService }: FtrProviderContext): void => { }); beforeEach(async () => { - await createSignalsIndex(supertest, log); + await createAlertsIndex(supertest, log); }); afterEach(async () => { @@ -70,14 +69,14 @@ export default ({ getService }: FtrProviderContext): void => { await deleteAllRules(supertest, log); }); - it('should ignore the field of "testing_ignored"', async () => { - const rule = getEqlRuleForSignalTesting(['ignore_fields']); + it('@skipInQA should ignore the field of "testing_ignored"', async () => { + const rule = getEqlRuleForAlertTesting(['ignore_fields']); const { id } = await createRule(supertest, log, rule); await waitForRuleSuccess({ supertest, log, id }); - await waitForSignalsToBePresent(supertest, log, 4, [id]); - const signalsOpen = await getSignalsById(supertest, log, id); - const hits = signalsOpen.hits.hits + await waitForAlertsToBePresent(supertest, log, 4, [id]); + const alertsOpen = await getAlertsById(supertest, log, id); + const hits = alertsOpen.hits.hits .map((hit) => (hit._source as Ignore).testing_ignored) .sort(); @@ -85,27 +84,27 @@ export default ({ getService }: FtrProviderContext): void => { expect(hits).to.eql([undefined, undefined, undefined, undefined]); }); - it('should ignore the field of "testing_regex"', async () => { - const rule = getEqlRuleForSignalTesting(['ignore_fields']); + it('@skipInQA should ignore the field of "testing_regex"', async () => { + const rule = getEqlRuleForAlertTesting(['ignore_fields']); const { id } = await createRule(supertest, log, rule); await waitForRuleSuccess({ supertest, log, id }); - await waitForSignalsToBePresent(supertest, log, 4, [id]); - const signalsOpen = await getSignalsById(supertest, log, id); - const hits = signalsOpen.hits.hits.map((hit) => (hit._source as Ignore).testing_regex).sort(); + await waitForAlertsToBePresent(supertest, log, 4, [id]); + const alertsOpen = await getAlertsById(supertest, log, id); + const hits = alertsOpen.hits.hits.map((hit) => (hit._source as Ignore).testing_regex).sort(); // Value should be "undefined for all records" expect(hits).to.eql([undefined, undefined, undefined, undefined]); }); it('should have the field of "normal_constant"', async () => { - const rule = getEqlRuleForSignalTesting(['ignore_fields']); + const rule = getEqlRuleForAlertTesting(['ignore_fields']); const { id } = await createRule(supertest, log, rule); await waitForRuleSuccess({ supertest, log, id }); - await waitForSignalsToBePresent(supertest, log, 4, [id]); - const signalsOpen = await getSignalsById(supertest, log, id); - const hits = signalsOpen.hits.hits + await waitForAlertsToBePresent(supertest, log, 4, [id]); + const alertsOpen = await getAlertsById(supertest, log, id); + const hits = alertsOpen.hits.hits .map((hit) => (hit._source as Ignore).normal_constant) .sort(); @@ -115,13 +114,13 @@ export default ({ getService }: FtrProviderContext): void => { // TODO: Remove this test once https://github.com/elastic/elasticsearch/issues/77152 is fixed it('should ignore the field of "_ignored" when using EQL and index the data', async () => { - const rule = getEqlRuleForSignalTesting(['ignore_fields']); + const rule = getEqlRuleForAlertTesting(['ignore_fields']); const { id } = await createRule(supertest, log, rule); await waitForRuleSuccess({ supertest, log, id }); - await waitForSignalsToBePresent(supertest, log, 4, [id]); - const signalsOpen = await getSignalsById(supertest, log, id); - const hits = signalsOpen.hits.hits.map((hit) => (hit._source as Ignore).small_field).sort(); + await waitForAlertsToBePresent(supertest, log, 4, [id]); + const alertsOpen = await getAlertsById(supertest, log, id); + const hits = alertsOpen.hits.hits.map((hit) => (hit._source as Ignore).small_field).sort(); // We just test a constant value to ensure this did not blow up on us and did index data. expect(hits).to.eql([ diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/rule_execution_logic/index.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/rule_execution_logic/index.ts new file mode 100644 index 0000000000000..b497472e0b574 --- /dev/null +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/rule_execution_logic/index.ts @@ -0,0 +1,18 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { FtrProviderContext } from '../../../../ftr_provider_context'; + +export default function ({ loadTestFile }: FtrProviderContext) { + describe('Rule execution logic API', function () { + loadTestFile(require.resolve('./keyword_family')); + loadTestFile(require.resolve('./ignore_fields')); + loadTestFile(require.resolve('./runtime')); + loadTestFile(require.resolve('./execution_logic')); + loadTestFile(require.resolve('./timestamps')); + }); +} diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/group5/keyword_family/README.md b/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/rule_execution_logic/keyword_family/README.md similarity index 100% rename from x-pack/test/detection_engine_api_integration/security_and_spaces/group5/keyword_family/README.md rename to x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/rule_execution_logic/keyword_family/README.md diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/group5/keyword_family/const_keyword.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/rule_execution_logic/keyword_family/const_keyword.ts similarity index 66% rename from x-pack/test/detection_engine_api_integration/security_and_spaces/group5/keyword_family/const_keyword.ts rename to x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/rule_execution_logic/keyword_family/const_keyword.ts index 44c25e51ba11f..0e3d01dc1ca22 100644 --- a/x-pack/test/detection_engine_api_integration/security_and_spaces/group5/keyword_family/const_keyword.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/rule_execution_logic/keyword_family/const_keyword.ts @@ -12,28 +12,27 @@ import { } from '@kbn/security-solution-plugin/common/api/detection_engine'; import { ALERT_THRESHOLD_RESULT } from '@kbn/security-solution-plugin/common/field_maps/field_names'; -import { FtrProviderContext } from '../../../common/ftr_provider_context'; import { createRule, - createSignalsIndex, + createAlertsIndex, deleteAllRules, deleteAllAlerts, - getEqlRuleForSignalTesting, - getRuleForSignalTesting, - getSignalsById, - getThresholdRuleForSignalTesting, + getEqlRuleForAlertTesting, + getRuleForAlertTesting, + getAlertsById, + getThresholdRuleForAlertTesting, waitForRuleSuccess, - waitForSignalsToBePresent, + waitForAlertsToBePresent, } from '../../../utils'; +import { FtrProviderContext } from '../../../../../ftr_provider_context'; -// eslint-disable-next-line import/no-default-export export default ({ getService }: FtrProviderContext) => { const supertest = getService('supertest'); const esArchiver = getService('esArchiver'); const log = getService('log'); const es = getService('es'); - describe('Rule detects against a keyword of event.dataset', () => { + describe('@ess @serverless Rule detects against a keyword of event.dataset', () => { before(async () => { await esArchiver.load('x-pack/test/functional/es_archives/rule_keyword_family/const_keyword'); }); @@ -45,7 +44,7 @@ export default ({ getService }: FtrProviderContext) => { }); beforeEach(async () => { - await createSignalsIndex(supertest, log); + await createAlertsIndex(supertest, log); }); afterEach(async () => { @@ -54,28 +53,28 @@ export default ({ getService }: FtrProviderContext) => { }); describe('"kql" rule type', () => { - it('should detect the "dataset_name_1" from "event.dataset" and have 4 signals', async () => { + it('should detect the "dataset_name_1" from "event.dataset" and have 4 alerts', async () => { const rule = { - ...getRuleForSignalTesting(['const_keyword']), + ...getRuleForAlertTesting(['const_keyword']), query: 'event.dataset: "dataset_name_1"', }; const { id } = await createRule(supertest, log, rule); await waitForRuleSuccess({ supertest, log, id }); - await waitForSignalsToBePresent(supertest, log, 4, [id]); - const signalsOpen = await getSignalsById(supertest, log, id); - expect(signalsOpen.hits.hits.length).to.eql(4); + await waitForAlertsToBePresent(supertest, log, 4, [id]); + const alertsOpen = await getAlertsById(supertest, log, id); + expect(alertsOpen.hits.hits.length).to.eql(4); }); - it('should copy the dataset_name_1 from the index into the signal', async () => { + it('should copy the dataset_name_1 from the index into the alert', async () => { const rule = { - ...getRuleForSignalTesting(['const_keyword']), + ...getRuleForAlertTesting(['const_keyword']), query: 'event.dataset: "dataset_name_1"', }; const { id } = await createRule(supertest, log, rule); await waitForRuleSuccess({ supertest, log, id }); - await waitForSignalsToBePresent(supertest, log, 4, [id]); - const signalsOpen = await getSignalsById(supertest, log, id); - const hits = signalsOpen.hits.hits.map((hit) => hit._source?.['event.dataset']).sort(); + await waitForAlertsToBePresent(supertest, log, 4, [id]); + const alertsOpen = await getAlertsById(supertest, log, id); + const hits = alertsOpen.hits.hits.map((hit) => hit._source?.['event.dataset']).sort(); expect(hits).to.eql([ 'dataset_name_1', 'dataset_name_1', @@ -86,30 +85,30 @@ export default ({ getService }: FtrProviderContext) => { }); describe('"eql" rule type', () => { - it('should detect the "dataset_name_1" from "event.dataset" and have 4 signals', async () => { + it('should detect the "dataset_name_1" from "event.dataset" and have 4 alerts', async () => { const rule: EqlRuleCreateProps = { - ...getEqlRuleForSignalTesting(['const_keyword']), + ...getEqlRuleForAlertTesting(['const_keyword']), query: 'any where event.dataset=="dataset_name_1"', }; const { id } = await createRule(supertest, log, rule); await waitForRuleSuccess({ supertest, log, id }); - await waitForSignalsToBePresent(supertest, log, 4, [id]); - const signalsOpen = await getSignalsById(supertest, log, id); - expect(signalsOpen.hits.hits.length).to.eql(4); + await waitForAlertsToBePresent(supertest, log, 4, [id]); + const alertsOpen = await getAlertsById(supertest, log, id); + expect(alertsOpen.hits.hits.length).to.eql(4); }); it('should copy the "dataset_name_1" from "event.dataset"', async () => { const rule: EqlRuleCreateProps = { - ...getEqlRuleForSignalTesting(['const_keyword']), + ...getEqlRuleForAlertTesting(['const_keyword']), query: 'any where event.dataset=="dataset_name_1"', }; const { id } = await createRule(supertest, log, rule); await waitForRuleSuccess({ supertest, log, id }); - await waitForSignalsToBePresent(supertest, log, 4, [id]); - const signalsOpen = await getSignalsById(supertest, log, id); - const hits = signalsOpen.hits.hits.map((hit) => hit._source?.['event.dataset']).sort(); + await waitForAlertsToBePresent(supertest, log, 4, [id]); + const alertsOpen = await getAlertsById(supertest, log, id); + const hits = alertsOpen.hits.hits.map((hit) => hit._source?.['event.dataset']).sort(); expect(hits).to.eql([ 'dataset_name_1', 'dataset_name_1', @@ -122,7 +121,7 @@ export default ({ getService }: FtrProviderContext) => { describe('"threshold" rule type', async () => { it('should detect the "dataset_name_1" from "event.dataset"', async () => { const rule: ThresholdRuleCreateProps = { - ...getThresholdRuleForSignalTesting(['const_keyword']), + ...getThresholdRuleForAlertTesting(['const_keyword']), threshold: { field: 'event.dataset', value: 1, @@ -130,9 +129,9 @@ export default ({ getService }: FtrProviderContext) => { }; const { id } = await createRule(supertest, log, rule); await waitForRuleSuccess({ supertest, log, id }); - await waitForSignalsToBePresent(supertest, log, 1, [id]); - const signalsOpen = await getSignalsById(supertest, log, id); - const hits = signalsOpen.hits.hits + await waitForAlertsToBePresent(supertest, log, 1, [id]); + const alertsOpen = await getAlertsById(supertest, log, id); + const hits = alertsOpen.hits.hits .map((hit) => hit._source?.[ALERT_THRESHOLD_RESULT] ?? null) .sort(); expect(hits).to.eql([ diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/group5/keyword_family/index.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/rule_execution_logic/keyword_family/index.ts similarity index 81% rename from x-pack/test/detection_engine_api_integration/security_and_spaces/group5/keyword_family/index.ts rename to x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/rule_execution_logic/keyword_family/index.ts index 1ecb06fbed4e5..7244085b6eff2 100644 --- a/x-pack/test/detection_engine_api_integration/security_and_spaces/group5/keyword_family/index.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/rule_execution_logic/keyword_family/index.ts @@ -5,9 +5,8 @@ * 2.0. */ -import { FtrProviderContext } from '../../../common/ftr_provider_context'; +import { FtrProviderContext } from '../../../../../ftr_provider_context'; -// eslint-disable-next-line import/no-default-export export default ({ loadTestFile }: FtrProviderContext): void => { describe('Detection keyword family data types', function () { loadTestFile(require.resolve('./keyword')); diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/group5/keyword_family/keyword.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/rule_execution_logic/keyword_family/keyword.ts similarity index 72% rename from x-pack/test/detection_engine_api_integration/security_and_spaces/group5/keyword_family/keyword.ts rename to x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/rule_execution_logic/keyword_family/keyword.ts index 39d62da77a1a8..5a4dbf0929425 100644 --- a/x-pack/test/detection_engine_api_integration/security_and_spaces/group5/keyword_family/keyword.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/rule_execution_logic/keyword_family/keyword.ts @@ -13,21 +13,20 @@ import { ThresholdRuleCreateProps, } from '@kbn/security-solution-plugin/common/api/detection_engine'; import { ALERT_THRESHOLD_RESULT } from '@kbn/security-solution-plugin/common/field_maps/field_names'; -import { FtrProviderContext } from '../../../common/ftr_provider_context'; import { createRule, - createSignalsIndex, + createAlertsIndex, deleteAllRules, deleteAllAlerts, - getEqlRuleForSignalTesting, - getRuleForSignalTesting, - getSignalsById, - getThresholdRuleForSignalTesting, + getEqlRuleForAlertTesting, + getRuleForAlertTesting, + getAlertsById, + getThresholdRuleForAlertTesting, waitForRuleSuccess, - waitForSignalsToBePresent, + waitForAlertsToBePresent, } from '../../../utils'; +import { FtrProviderContext } from '../../../../../ftr_provider_context'; -// eslint-disable-next-line import/no-default-export export default ({ getService }: FtrProviderContext) => { const supertest = getService('supertest'); const esArchiver = getService('esArchiver'); @@ -44,7 +43,7 @@ export default ({ getService }: FtrProviderContext) => { }); beforeEach(async () => { - await createSignalsIndex(supertest, log); + await createAlertsIndex(supertest, log); }); afterEach(async () => { @@ -52,17 +51,17 @@ export default ({ getService }: FtrProviderContext) => { await deleteAllRules(supertest, log); }); - describe('"kql" rule type', () => { + describe('@ess @serverless "kql" rule type', () => { it('should detect the "dataset_name_1" from "event.dataset"', async () => { const rule: QueryRuleCreateProps = { - ...getRuleForSignalTesting(['keyword']), + ...getRuleForAlertTesting(['keyword']), query: 'event.dataset: "dataset_name_1"', }; const { id } = await createRule(supertest, log, rule); await waitForRuleSuccess({ supertest, log, id }); - await waitForSignalsToBePresent(supertest, log, 4, [id]); - const signalsOpen = await getSignalsById(supertest, log, id); - const hits = signalsOpen.hits.hits.map((hit) => hit._source?.['event.dataset']).sort(); + await waitForAlertsToBePresent(supertest, log, 4, [id]); + const alertsOpen = await getAlertsById(supertest, log, id); + const hits = alertsOpen.hits.hits.map((hit) => hit._source?.['event.dataset']).sort(); expect(hits).to.eql([ 'dataset_name_1', 'dataset_name_1', @@ -75,15 +74,15 @@ export default ({ getService }: FtrProviderContext) => { describe('"eql" rule type', () => { it('should detect the "dataset_name_1" from "event.dataset"', async () => { const rule: EqlRuleCreateProps = { - ...getEqlRuleForSignalTesting(['keyword']), + ...getEqlRuleForAlertTesting(['keyword']), query: 'any where event.dataset=="dataset_name_1"', }; const { id } = await createRule(supertest, log, rule); await waitForRuleSuccess({ supertest, log, id }); - await waitForSignalsToBePresent(supertest, log, 4, [id]); - const signalsOpen = await getSignalsById(supertest, log, id); - const hits = signalsOpen.hits.hits.map((hit) => hit._source?.['event.dataset']).sort(); + await waitForAlertsToBePresent(supertest, log, 4, [id]); + const alertsOpen = await getAlertsById(supertest, log, id); + const hits = alertsOpen.hits.hits.map((hit) => hit._source?.['event.dataset']).sort(); expect(hits).to.eql([ 'dataset_name_1', 'dataset_name_1', @@ -96,7 +95,7 @@ export default ({ getService }: FtrProviderContext) => { describe('"threshold" rule type', async () => { it('should detect the "dataset_name_1" from "event.dataset"', async () => { const rule: ThresholdRuleCreateProps = { - ...getThresholdRuleForSignalTesting(['keyword']), + ...getThresholdRuleForAlertTesting(['keyword']), threshold: { field: 'event.dataset', value: 1, @@ -104,9 +103,9 @@ export default ({ getService }: FtrProviderContext) => { }; const { id } = await createRule(supertest, log, rule); await waitForRuleSuccess({ supertest, log, id }); - await waitForSignalsToBePresent(supertest, log, 1, [id]); - const signalsOpen = await getSignalsById(supertest, log, id); - const hits = signalsOpen.hits.hits + await waitForAlertsToBePresent(supertest, log, 1, [id]); + const alertsOpen = await getAlertsById(supertest, log, id); + const hits = alertsOpen.hits.hits .map((hit) => hit._source?.[ALERT_THRESHOLD_RESULT] ?? null) .sort(); expect(hits).to.eql([ diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/group5/keyword_family/keyword_mixed_with_const.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/rule_execution_logic/keyword_family/keyword_mixed_with_const.ts similarity index 69% rename from x-pack/test/detection_engine_api_integration/security_and_spaces/group5/keyword_family/keyword_mixed_with_const.ts rename to x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/rule_execution_logic/keyword_family/keyword_mixed_with_const.ts index 50bbd7efde9f2..1353c0b6ca5ed 100644 --- a/x-pack/test/detection_engine_api_integration/security_and_spaces/group5/keyword_family/keyword_mixed_with_const.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/rule_execution_logic/keyword_family/keyword_mixed_with_const.ts @@ -12,27 +12,26 @@ import { } from '@kbn/security-solution-plugin/common/api/detection_engine'; import { ALERT_THRESHOLD_RESULT } from '@kbn/security-solution-plugin/common/field_maps/field_names'; -import { FtrProviderContext } from '../../../common/ftr_provider_context'; import { createRule, - createSignalsIndex, + createAlertsIndex, deleteAllRules, deleteAllAlerts, - getEqlRuleForSignalTesting, - getRuleForSignalTesting, - getSignalsById, + getEqlRuleForAlertTesting, + getRuleForAlertTesting, + getAlertsById, waitForRuleSuccess, - waitForSignalsToBePresent, + waitForAlertsToBePresent, } from '../../../utils'; +import { FtrProviderContext } from '../../../../../ftr_provider_context'; -// eslint-disable-next-line import/no-default-export export default ({ getService }: FtrProviderContext) => { const supertest = getService('supertest'); const esArchiver = getService('esArchiver'); const log = getService('log'); const es = getService('es'); - describe('Rule detects against a keyword and constant_keyword of event.dataset', () => { + describe('@ess @serverless Rule detects against a keyword and constant_keyword of event.dataset', () => { before(async () => { await esArchiver.load('x-pack/test/functional/es_archives/rule_keyword_family/const_keyword'); await esArchiver.load('x-pack/test/functional/es_archives/rule_keyword_family/keyword'); @@ -46,7 +45,7 @@ export default ({ getService }: FtrProviderContext) => { }); beforeEach(async () => { - await createSignalsIndex(supertest, log); + await createAlertsIndex(supertest, log); }); afterEach(async () => { @@ -55,28 +54,28 @@ export default ({ getService }: FtrProviderContext) => { }); describe('"kql" rule type', () => { - it('should detect the "dataset_name_1" from "event.dataset" and have 8 signals, 4 from each index', async () => { + it('should detect the "dataset_name_1" from "event.dataset" and have 8 alerts, 4 from each index', async () => { const rule = { - ...getRuleForSignalTesting(['keyword', 'const_keyword']), + ...getRuleForAlertTesting(['keyword', 'const_keyword']), query: 'event.dataset: "dataset_name_1"', }; const { id } = await createRule(supertest, log, rule); await waitForRuleSuccess({ supertest, log, id }); - await waitForSignalsToBePresent(supertest, log, 8, [id]); - const signalsOpen = await getSignalsById(supertest, log, id); - expect(signalsOpen.hits.hits.length).to.eql(8); + await waitForAlertsToBePresent(supertest, log, 8, [id]); + const alertsOpen = await getAlertsById(supertest, log, id); + expect(alertsOpen.hits.hits.length).to.eql(8); }); - it('should copy the dataset_name_1 from the index into the signal', async () => { + it('should copy the dataset_name_1 from the index into the alert', async () => { const rule = { - ...getRuleForSignalTesting(['keyword', 'const_keyword']), + ...getRuleForAlertTesting(['keyword', 'const_keyword']), query: 'event.dataset: "dataset_name_1"', }; const { id } = await createRule(supertest, log, rule); await waitForRuleSuccess({ supertest, log, id }); - await waitForSignalsToBePresent(supertest, log, 8, [id]); - const signalsOpen = await getSignalsById(supertest, log, id); - const hits = signalsOpen.hits.hits.map((hit) => hit._source?.['event.dataset']).sort(); + await waitForAlertsToBePresent(supertest, log, 8, [id]); + const alertsOpen = await getAlertsById(supertest, log, id); + const hits = alertsOpen.hits.hits.map((hit) => hit._source?.['event.dataset']).sort(); expect(hits).to.eql([ 'dataset_name_1', 'dataset_name_1', @@ -91,30 +90,30 @@ export default ({ getService }: FtrProviderContext) => { }); describe('"eql" rule type', () => { - it('should detect the "dataset_name_1" from "event.dataset" and have 8 signals, 4 from each index', async () => { + it('should detect the "dataset_name_1" from "event.dataset" and have 8 alerts, 4 from each index', async () => { const rule: EqlRuleCreateProps = { - ...getEqlRuleForSignalTesting(['keyword', 'const_keyword']), + ...getEqlRuleForAlertTesting(['keyword', 'const_keyword']), query: 'any where event.dataset=="dataset_name_1"', }; const { id } = await createRule(supertest, log, rule); await waitForRuleSuccess({ supertest, log, id }); - await waitForSignalsToBePresent(supertest, log, 8, [id]); - const signalsOpen = await getSignalsById(supertest, log, id); - expect(signalsOpen.hits.hits.length).to.eql(8); + await waitForAlertsToBePresent(supertest, log, 8, [id]); + const alertsOpen = await getAlertsById(supertest, log, id); + expect(alertsOpen.hits.hits.length).to.eql(8); }); it('should copy the "dataset_name_1" from "event.dataset"', async () => { const rule: EqlRuleCreateProps = { - ...getEqlRuleForSignalTesting(['keyword', 'const_keyword']), + ...getEqlRuleForAlertTesting(['keyword', 'const_keyword']), query: 'any where event.dataset=="dataset_name_1"', }; const { id } = await createRule(supertest, log, rule); await waitForRuleSuccess({ supertest, log, id }); - await waitForSignalsToBePresent(supertest, log, 8, [id]); - const signalsOpen = await getSignalsById(supertest, log, id); - const hits = signalsOpen.hits.hits.map((hit) => hit._source?.['event.dataset']).sort(); + await waitForAlertsToBePresent(supertest, log, 8, [id]); + const alertsOpen = await getAlertsById(supertest, log, id); + const hits = alertsOpen.hits.hits.map((hit) => hit._source?.['event.dataset']).sort(); expect(hits).to.eql([ 'dataset_name_1', 'dataset_name_1', @@ -131,7 +130,7 @@ export default ({ getService }: FtrProviderContext) => { describe('"threshold" rule type', async () => { it('should detect the "dataset_name_1" from "event.dataset"', async () => { const rule: ThresholdRuleCreateProps = { - ...getRuleForSignalTesting(['keyword', 'const_keyword']), + ...getRuleForAlertTesting(['keyword', 'const_keyword']), rule_id: 'threshold-rule', type: 'threshold', language: 'kuery', @@ -143,9 +142,9 @@ export default ({ getService }: FtrProviderContext) => { }; const { id } = await createRule(supertest, log, rule); await waitForRuleSuccess({ supertest, log, id }); - await waitForSignalsToBePresent(supertest, log, 1, [id]); - const signalsOpen = await getSignalsById(supertest, log, id); - const hits = signalsOpen.hits.hits + await waitForAlertsToBePresent(supertest, log, 1, [id]); + const alertsOpen = await getAlertsById(supertest, log, id); + const hits = alertsOpen.hits.hits .map((hit) => hit._source?.[ALERT_THRESHOLD_RESULT] ?? null) .sort(); expect(hits).to.eql([ diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/group10/runtime.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/rule_execution_logic/runtime.ts similarity index 70% rename from x-pack/test/detection_engine_api_integration/security_and_spaces/group10/runtime.ts rename to x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/rule_execution_logic/runtime.ts index 83c988c5ff9fd..030f2eafd6a1e 100644 --- a/x-pack/test/detection_engine_api_integration/security_and_spaces/group10/runtime.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/rule_execution_logic/runtime.ts @@ -8,19 +8,18 @@ import expect from '@kbn/expect'; import { performance } from 'perf_hooks'; -import { FtrProviderContext } from '../../common/ftr_provider_context'; import { createRule, - createSignalsIndex, + createAlertsIndex, deleteAllRules, deleteAllAlerts, - getRuleForSignalTesting, - getSignalsById, + getRuleForAlertTesting, + getAlertsById, waitForRuleSuccess, - waitForSignalsToBePresent, + waitForAlertsToBePresent, } from '../../utils'; +import { FtrProviderContext } from '../../../../ftr_provider_context'; -// eslint-disable-next-line import/no-default-export export default ({ getService }: FtrProviderContext) => { const supertest = getService('supertest'); const esArchiver = getService('esArchiver'); @@ -33,7 +32,7 @@ export default ({ getService }: FtrProviderContext) => { } // FAILING ES PROMOTION: https://github.com/elastic/kibana/issues/138923 - describe('Tests involving runtime fields of source indexes and the signals index', () => { + describe('@ess @serverless Tests involving runtime fields of source indexes and the alerts index', () => { before(async () => { await esArchiver.load('x-pack/test/functional/es_archives/security_solution/runtime'); }); @@ -44,7 +43,7 @@ export default ({ getService }: FtrProviderContext) => { describe('Regular runtime field mappings', () => { beforeEach(async () => { - await createSignalsIndex(supertest, log); + await createAlertsIndex(supertest, log); }); afterEach(async () => { @@ -53,7 +52,7 @@ export default ({ getService }: FtrProviderContext) => { }); it('should execute a rule to completion and not timeout when there are a lot of runtime fields', async () => { - const rule = getRuleForSignalTesting(['runtime']); + const rule = getRuleForAlertTesting(['runtime']); const { id } = await createRule(supertest, log, rule); const start = performance.now(); await waitForRuleSuccess({ supertest, log, id }); @@ -61,26 +60,26 @@ export default ({ getService }: FtrProviderContext) => { expect(end - start).to.be.lessThan(10000); }); - it('should copy normal non-runtime data set from the source index into the signals index in the same position when the target is ECS compatible', async () => { - const rule = getRuleForSignalTesting(['runtime']); + it('should copy normal non-runtime data set from the source index into the alerts index in the same position when the target is ECS compatible', async () => { + const rule = getRuleForAlertTesting(['runtime']); const { id } = await createRule(supertest, log, rule); await waitForRuleSuccess({ supertest, log, id }); - await waitForSignalsToBePresent(supertest, log, 4, [id]); - const signalsOpen = await getSignalsById(supertest, log, id); - const hits = signalsOpen.hits.hits - .map((signal) => (signal._source?.host as Runtime).name) + await waitForAlertsToBePresent(supertest, log, 4, [id]); + const alertsOpen = await getAlertsById(supertest, log, id); + const hits = alertsOpen.hits.hits + .map((alert) => (alert._source?.host as Runtime).name) .sort(); expect(hits).to.eql(['host name 1', 'host name 2', 'host name 3', 'host name 4']); }); - it('should copy "runtime mapping" data from a source index into the signals index in the same position when the target is ECS compatible', async () => { - const rule = getRuleForSignalTesting(['runtime']); + it('should copy "runtime mapping" data from a source index into the alerts index in the same position when the target is ECS compatible', async () => { + const rule = getRuleForAlertTesting(['runtime']); const { id } = await createRule(supertest, log, rule); await waitForRuleSuccess({ supertest, log, id }); - await waitForSignalsToBePresent(supertest, log, 4, [id]); - const signalsOpen = await getSignalsById(supertest, log, id); - const hits = signalsOpen.hits.hits - .map((signal) => (signal._source?.host as Runtime).hostname) + await waitForAlertsToBePresent(supertest, log, 4, [id]); + const alertsOpen = await getAlertsById(supertest, log, id); + const hits = alertsOpen.hits.hits + .map((alert) => (alert._source?.host as Runtime).hostname) .sort(); expect(hits).to.eql(['host name 1', 'host name 2', 'host name 3', 'host name 4']); }); @@ -88,7 +87,7 @@ export default ({ getService }: FtrProviderContext) => { describe('Runtime field mappings that have conflicts within them', () => { beforeEach(async () => { - await createSignalsIndex(supertest, log); + await createAlertsIndex(supertest, log); await esArchiver.load( 'x-pack/test/functional/es_archives/security_solution/runtime_conflicting_fields' ); @@ -107,14 +106,14 @@ export default ({ getService }: FtrProviderContext) => { * risk with overwriting fields in the strategy we are currently using in detection engine. If you swap, change the strategies * because we decide to overwrite "_source" values with "fields", then expect to change this test. */ - it('should NOT copy normal non-runtime data set from the source index into the signals index in the same position when the target is ECS compatible', async () => { - const rule = getRuleForSignalTesting(['runtime_conflicting_fields']); + it('should NOT copy normal non-runtime data set from the source index into the alerts index in the same position when the target is ECS compatible', async () => { + const rule = getRuleForAlertTesting(['runtime_conflicting_fields']); const { id } = await createRule(supertest, log, rule); await waitForRuleSuccess({ supertest, log, id }); - await waitForSignalsToBePresent(supertest, log, 4, [id]); - const signalsOpen = await getSignalsById(supertest, log, id); - const hits = signalsOpen.hits.hits - .map((signal) => signal._source?.host as Array<{ name: string }>) + await waitForAlertsToBePresent(supertest, log, 4, [id]); + const alertsOpen = await getAlertsById(supertest, log, id); + const hits = alertsOpen.hits.hits + .map((alert) => alert._source?.host as Array<{ name: string }>) .map((host) => { // sort the inner array elements first return host.sort((a, b) => a.name.localeCompare(b.name)); @@ -164,15 +163,13 @@ export default ({ getService }: FtrProviderContext) => { * fields as arrays of objects since the objects are flattened in "fields" and we detect something already there so we skip * this shadowed runtime data as it is ambiguous of where we would put it in the array. */ - it('should NOT copy "runtime mapping" data from a source index into the signals index in the same position when the target is ECS compatible', async () => { - const rule = getRuleForSignalTesting(['runtime_conflicting_fields']); + it('should NOT copy "runtime mapping" data from a source index into the alerts index in the same position when the target is ECS compatible', async () => { + const rule = getRuleForAlertTesting(['runtime_conflicting_fields']); const { id } = await createRule(supertest, log, rule); await waitForRuleSuccess({ supertest, log, id }); - await waitForSignalsToBePresent(supertest, log, 4, [id]); - const signalsOpen = await getSignalsById(supertest, log, id); - const hits = signalsOpen.hits.hits.map( - (signal) => (signal._source?.host as Runtime).hostname - ); + await waitForAlertsToBePresent(supertest, log, 4, [id]); + const alertsOpen = await getAlertsById(supertest, log, id); + const hits = alertsOpen.hits.hits.map((alert) => (alert._source?.host as Runtime).hostname); expect(hits).to.eql([undefined, undefined, undefined, undefined]); }); }); diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/group10/timestamps.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/rule_execution_logic/timestamps.ts similarity index 58% rename from x-pack/test/detection_engine_api_integration/security_and_spaces/group10/timestamps.ts rename to x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/rule_execution_logic/timestamps.ts index ef27b7c7ff4bd..d7c645c115082 100644 --- a/x-pack/test/detection_engine_api_integration/security_and_spaces/group10/timestamps.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/rule_execution_logic/timestamps.ts @@ -14,37 +14,41 @@ import { } from '@kbn/security-solution-plugin/common/api/detection_engine'; import { ALERT_ORIGINAL_TIME } from '@kbn/security-solution-plugin/common/field_maps/field_names'; -import { FtrProviderContext } from '../../common/ftr_provider_context'; import { - createSignalsIndex, + createAlertsIndex, deleteAllRules, deleteAllAlerts, createRule, waitForRuleSuccess, - waitForSignalsToBePresent, - getOpenSignals, - getRuleForSignalTesting, - getSignalsByIds, - getEqlRuleForSignalTesting, + waitForAlertsToBePresent, + getOpenAlerts, + getRuleForAlertTesting, + getAlertsByIds, + getEqlRuleForAlertTesting, waitForRulePartialFailure, } from '../../utils'; +import { FtrProviderContext } from '../../../../ftr_provider_context'; +import { EsArchivePathBuilder } from '../../../../es_archive_path_builder'; -// eslint-disable-next-line import/no-default-export export default ({ getService }: FtrProviderContext) => { const supertest = getService('supertest'); const esArchiver = getService('esArchiver'); const es = getService('es'); const log = getService('log'); - + // TODO: add a new service + const config = getService('config'); + const isServerless = config.get('serverless'); + const dataPathBuilder = new EsArchivePathBuilder(isServerless); + const path = dataPathBuilder.getPath('auditbeat/hosts'); /** - * Tests around timestamps within signals such as the copying of timestamps correctly into + * Tests around timestamps within alerts such as the copying of timestamps correctly into * the "signal.original_time" field, ensuring that timestamp overrides operate, and ensuring that * partial errors happen correctly */ - describe('timestamp tests', () => { - describe('Signals generated from events with a timestamp in seconds is converted correctly into the forced ISO8601 format when copying', () => { + describe('@ess @serverless timestamp tests', () => { + describe('alerts generated from events with a timestamp in seconds is converted correctly into the forced ISO8601 format when copying', () => { beforeEach(async () => { - await createSignalsIndex(supertest, log); + await createAlertsIndex(supertest, log); await esArchiver.load( 'x-pack/test/functional/es_archives/security_solution/timestamp_in_seconds' ); @@ -66,58 +70,50 @@ export default ({ getService }: FtrProviderContext) => { describe('KQL query', () => { it('should convert the @timestamp which is epoch_seconds into the correct ISO format', async () => { - const rule = getRuleForSignalTesting(['timestamp_in_seconds']); + const rule = getRuleForAlertTesting(['timestamp_in_seconds']); const { id } = await createRule(supertest, log, rule); await waitForRuleSuccess({ supertest, log, id }); - await waitForSignalsToBePresent(supertest, log, 1, [id]); - const signalsOpen = await getSignalsByIds(supertest, log, [id]); - const hits = signalsOpen.hits.hits - .map((hit) => hit._source?.[ALERT_ORIGINAL_TIME]) - .sort(); + await waitForAlertsToBePresent(supertest, log, 1, [id]); + const alertsOpen = await getAlertsByIds(supertest, log, [id]); + const hits = alertsOpen.hits.hits.map((hit) => hit._source?.[ALERT_ORIGINAL_TIME]).sort(); expect(hits).to.eql(['2021-06-02T23:33:15.000Z']); }); it('should still use the @timestamp field even with an override field. It should never use the override field', async () => { const rule: QueryRuleCreateProps = { - ...getRuleForSignalTesting(['myfakeindex-5']), + ...getRuleForAlertTesting(['myfakeindex-5']), timestamp_override: 'event.ingested', }; const { id } = await createRule(supertest, log, rule); await waitForRuleSuccess({ supertest, log, id }); - await waitForSignalsToBePresent(supertest, log, 1, [id]); - const signalsOpen = await getSignalsByIds(supertest, log, [id]); - const hits = signalsOpen.hits.hits - .map((hit) => hit._source?.[ALERT_ORIGINAL_TIME]) - .sort(); + await waitForAlertsToBePresent(supertest, log, 1, [id]); + const alertsOpen = await getAlertsByIds(supertest, log, [id]); + const hits = alertsOpen.hits.hits.map((hit) => hit._source?.[ALERT_ORIGINAL_TIME]).sort(); expect(hits).to.eql(['2020-12-16T15:16:18.000Z']); }); }); describe('EQL query', () => { it('should convert the @timestamp which is epoch_seconds into the correct ISO format for EQL', async () => { - const rule = getEqlRuleForSignalTesting(['timestamp_in_seconds']); + const rule = getEqlRuleForAlertTesting(['timestamp_in_seconds']); const { id } = await createRule(supertest, log, rule); await waitForRuleSuccess({ supertest, log, id }); - await waitForSignalsToBePresent(supertest, log, 1, [id]); - const signalsOpen = await getSignalsByIds(supertest, log, [id]); - const hits = signalsOpen.hits.hits - .map((hit) => hit._source?.[ALERT_ORIGINAL_TIME]) - .sort(); + await waitForAlertsToBePresent(supertest, log, 1, [id]); + const alertsOpen = await getAlertsByIds(supertest, log, [id]); + const hits = alertsOpen.hits.hits.map((hit) => hit._source?.[ALERT_ORIGINAL_TIME]).sort(); expect(hits).to.eql(['2021-06-02T23:33:15.000Z']); }); it('should still use the @timestamp field even with an override field. It should never use the override field', async () => { const rule: EqlRuleCreateProps = { - ...getEqlRuleForSignalTesting(['myfakeindex-5']), + ...getEqlRuleForAlertTesting(['myfakeindex-5']), timestamp_override: 'event.ingested', }; const { id } = await createRule(supertest, log, rule); await waitForRuleSuccess({ supertest, log, id }); - await waitForSignalsToBePresent(supertest, log, 1, [id]); - const signalsOpen = await getSignalsByIds(supertest, log, [id]); - const hits = signalsOpen.hits.hits - .map((hit) => hit._source?.[ALERT_ORIGINAL_TIME]) - .sort(); + await waitForAlertsToBePresent(supertest, log, 1, [id]); + const alertsOpen = await getAlertsByIds(supertest, log, [id]); + const hits = alertsOpen.hits.hits.map((hit) => hit._source?.[ALERT_ORIGINAL_TIME]).sort(); expect(hits).to.eql(['2020-12-16T15:16:18.000Z']); }); }); @@ -129,10 +125,10 @@ export default ({ getService }: FtrProviderContext) => { * If no timestamp override field exists in the indices but one was provided to the rule, * the rule's query will additionally search for events using the `@timestamp` field */ - describe('Signals generated from events with timestamp override field', async () => { + describe('alerts generated from events with timestamp override field', async () => { beforeEach(async () => { await deleteAllAlerts(supertest, log, es); - await createSignalsIndex(supertest, log); + await createAlertsIndex(supertest, log); await esArchiver.load( 'x-pack/test/functional/es_archives/security_solution/timestamp_override_1' ); @@ -165,9 +161,9 @@ export default ({ getService }: FtrProviderContext) => { }); describe('KQL', () => { - it('should generate signals with event.ingested, @timestamp and (event.ingested + timestamp)', async () => { + it('should generate alerts with event.ingested, @timestamp and (event.ingested + timestamp)', async () => { const rule: QueryRuleCreateProps = { - ...getRuleForSignalTesting(['myfa*']), + ...getRuleForAlertTesting(['myfa*']), timestamp_override: 'event.ingested', }; @@ -178,17 +174,17 @@ export default ({ getService }: FtrProviderContext) => { log, id, }); - await waitForSignalsToBePresent(supertest, log, 3, [id]); - const signalsResponse = await getSignalsByIds(supertest, log, [id], 3); - const signals = signalsResponse.hits.hits.map((hit) => hit._source); - const signalsOrderedByEventId = orderBy(signals, 'signal.parent.id', 'asc'); + await waitForAlertsToBePresent(supertest, log, 3, [id]); + const alertsResponse = await getAlertsByIds(supertest, log, [id], 3); + const alerts = alertsResponse.hits.hits.map((hit) => hit._source); + const alertsOrderedByEventId = orderBy(alerts, 'alert.parent.id', 'asc'); - expect(signalsOrderedByEventId.length).equal(3); + expect(alertsOrderedByEventId.length).equal(3); }); - it('should generate 2 signals with event.ingested when timestamp fallback is disabled', async () => { + it('should generate 2 alerts with event.ingested when timestamp fallback is disabled', async () => { const rule: QueryRuleCreateProps = { - ...getRuleForSignalTesting(['myfa*']), + ...getRuleForAlertTesting(['myfa*']), rule_id: 'rule-without-timestamp-fallback', timestamp_override: 'event.ingested', timestamp_override_fallback_disabled: true, @@ -201,16 +197,16 @@ export default ({ getService }: FtrProviderContext) => { log, id, }); - await waitForSignalsToBePresent(supertest, log, 2, [id]); - const signalsResponse = await getSignalsByIds(supertest, log, [id], 2); - const signals = signalsResponse.hits.hits.map((hit) => hit._source); - const signalsOrderedByEventId = orderBy(signals, 'signal.parent.id', 'asc'); + await waitForAlertsToBePresent(supertest, log, 2, [id]); + const alertsResponse = await getAlertsByIds(supertest, log, [id], 2); + const alerts = alertsResponse.hits.hits.map((hit) => hit._source); + const alertsOrderedByEventId = orderBy(alerts, 'alert.parent.id', 'asc'); - expect(signalsOrderedByEventId.length).equal(2); + expect(alertsOrderedByEventId.length).equal(2); }); - it('should generate 2 signals with @timestamp', async () => { - const rule: QueryRuleCreateProps = getRuleForSignalTesting(['myfa*']); + it('should generate 2 alerts with @timestamp', async () => { + const rule: QueryRuleCreateProps = getRuleForAlertTesting(['myfa*']); const { id } = await createRule(supertest, log, rule); @@ -219,17 +215,17 @@ export default ({ getService }: FtrProviderContext) => { log, id, }); - await waitForSignalsToBePresent(supertest, log, 2, [id]); - const signalsResponse = await getSignalsByIds(supertest, log, [id]); - const signals = signalsResponse.hits.hits.map((hit) => hit._source); - const signalsOrderedByEventId = orderBy(signals, 'signal.parent.id', 'asc'); + await waitForAlertsToBePresent(supertest, log, 2, [id]); + const alertsResponse = await getAlertsByIds(supertest, log, [id]); + const alerts = alertsResponse.hits.hits.map((hit) => hit._source); + const alertsOrderedByEventId = orderBy(alerts, 'alert.parent.id', 'asc'); - expect(signalsOrderedByEventId.length).equal(2); + expect(alertsOrderedByEventId.length).equal(2); }); - it('should generate 2 signals when timestamp override does not exist', async () => { + it('should generate 2 alerts when timestamp override does not exist', async () => { const rule: QueryRuleCreateProps = { - ...getRuleForSignalTesting(['myfa*']), + ...getRuleForAlertTesting(['myfa*']), timestamp_override: 'event.fakeingestfield', }; const { id } = await createRule(supertest, log, rule); @@ -239,50 +235,50 @@ export default ({ getService }: FtrProviderContext) => { log, id, }); - await waitForSignalsToBePresent(supertest, log, 2, [id]); - const signalsResponse = await getSignalsByIds(supertest, log, [id, id]); - const signals = signalsResponse.hits.hits.map((hit) => hit._source); - const signalsOrderedByEventId = orderBy(signals, 'signal.parent.id', 'asc'); + await waitForAlertsToBePresent(supertest, log, 2, [id]); + const alertsResponse = await getAlertsByIds(supertest, log, [id, id]); + const alerts = alertsResponse.hits.hits.map((hit) => hit._source); + const alertsOrderedByEventId = orderBy(alerts, 'alert.parent.id', 'asc'); - expect(signalsOrderedByEventId.length).equal(2); + expect(alertsOrderedByEventId.length).equal(2); }); - it('should not generate any signals when timestamp override does not exist and timestamp fallback is disabled', async () => { + it('should not generate any alerts when timestamp override does not exist and timestamp fallback is disabled', async () => { const rule: QueryRuleCreateProps = { - ...getRuleForSignalTesting(['myfa*']), + ...getRuleForAlertTesting(['myfa*']), rule_id: 'rule-without-timestamp-fallback', timestamp_override: 'event.fakeingestfield', timestamp_override_fallback_disabled: true, }; const createdRule = await createRule(supertest, log, rule); - const signalsOpen = await getOpenSignals( + const alertsOpen = await getOpenAlerts( supertest, log, es, createdRule, RuleExecutionStatusEnum['partial failure'] ); - expect(signalsOpen.hits.hits.length).eql(0); + expect(alertsOpen.hits.hits.length).eql(0); }); /** * We should not use the timestamp override as the "original_time" as that can cause * confusion if you have both a timestamp and an override in the source event. Instead the "original_time" - * field should only be overridden by the "timestamp" since when we generate a signal - * and we add a new timestamp to the signal. + * field should only be overridden by the "timestamp" since when we generate a alert + * and we add a new timestamp to the alert. */ it('should NOT use the timestamp override as the "original_time"', async () => { const rule: QueryRuleCreateProps = { - ...getRuleForSignalTesting(['myfakeindex-2']), + ...getRuleForAlertTesting(['myfakeindex-2']), timestamp_override: 'event.ingested', }; const { id } = await createRule(supertest, log, rule); await waitForRuleSuccess({ supertest, log, id }); - await waitForSignalsToBePresent(supertest, log, 1, [id]); - const signalsResponse = await getSignalsByIds(supertest, log, [id, id]); - const hits = signalsResponse.hits.hits + await waitForAlertsToBePresent(supertest, log, 1, [id]); + const alertsResponse = await getAlertsByIds(supertest, log, [id, id]); + const hits = alertsResponse.hits.hits .map((hit) => hit._source?.[ALERT_ORIGINAL_TIME]) .sort(); expect(hits).to.eql([undefined]); @@ -290,8 +286,8 @@ export default ({ getService }: FtrProviderContext) => { }); describe('EQL', () => { - it('should generate 2 signals with @timestamp', async () => { - const rule: EqlRuleCreateProps = getEqlRuleForSignalTesting(['myfa*']); + it('should generate 2 alerts with @timestamp', async () => { + const rule: EqlRuleCreateProps = getEqlRuleForAlertTesting(['myfa*']); const { id } = await createRule(supertest, log, rule); @@ -300,17 +296,17 @@ export default ({ getService }: FtrProviderContext) => { log, id, }); - await waitForSignalsToBePresent(supertest, log, 2, [id]); - const signalsResponse = await getSignalsByIds(supertest, log, [id]); - const signals = signalsResponse.hits.hits.map((hit) => hit._source); - const signalsOrderedByEventId = orderBy(signals, 'signal.parent.id', 'asc'); + await waitForAlertsToBePresent(supertest, log, 2, [id]); + const alertsResponse = await getAlertsByIds(supertest, log, [id]); + const alerts = alertsResponse.hits.hits.map((hit) => hit._source); + const alertsOrderedByEventId = orderBy(alerts, 'alert.parent.id', 'asc'); - expect(signalsOrderedByEventId.length).equal(2); + expect(alertsOrderedByEventId.length).equal(2); }); - it('should generate 2 signals when timestamp override does not exist', async () => { + it('should generate 2 alerts when timestamp override does not exist', async () => { const rule: EqlRuleCreateProps = { - ...getEqlRuleForSignalTesting(['myfa*']), + ...getEqlRuleForAlertTesting(['myfa*']), timestamp_override: 'event.fakeingestfield', }; const { id } = await createRule(supertest, log, rule); @@ -320,44 +316,44 @@ export default ({ getService }: FtrProviderContext) => { log, id, }); - await waitForSignalsToBePresent(supertest, log, 2, [id]); - const signalsResponse = await getSignalsByIds(supertest, log, [id, id]); - const signals = signalsResponse.hits.hits.map((hit) => hit._source); - const signalsOrderedByEventId = orderBy(signals, 'signal.parent.id', 'asc'); + await waitForAlertsToBePresent(supertest, log, 2, [id]); + const alertsResponse = await getAlertsByIds(supertest, log, [id, id]); + const alerts = alertsResponse.hits.hits.map((hit) => hit._source); + const alertsOrderedByEventId = orderBy(alerts, 'alert.parent.id', 'asc'); - expect(signalsOrderedByEventId.length).equal(2); + expect(alertsOrderedByEventId.length).equal(2); }); - it('should not generate any signals when timestamp override does not exist and timestamp fallback is disabled', async () => { + it('should not generate any alerts when timestamp override does not exist and timestamp fallback is disabled', async () => { const rule: EqlRuleCreateProps = { - ...getEqlRuleForSignalTesting(['myfa*']), + ...getEqlRuleForAlertTesting(['myfa*']), timestamp_override: 'event.fakeingestfield', timestamp_override_fallback_disabled: true, }; const createdRule = await createRule(supertest, log, rule); - const signalsOpen = await getOpenSignals( + const alertsOpen = await getOpenAlerts( supertest, log, es, createdRule, RuleExecutionStatusEnum['partial failure'] ); - expect(signalsOpen.hits.hits.length).eql(0); + expect(alertsOpen.hits.hits.length).eql(0); }); }); }); - describe('Signals generated from events with timestamp override field and ensures search_after continues to work when documents are missing timestamp override field', () => { + describe('alerts generated from events with timestamp override field and ensures search_after continues to work when documents are missing timestamp override field', () => { before(async () => { - await esArchiver.load('x-pack/test/functional/es_archives/auditbeat/hosts'); + await esArchiver.load(path); }); after(async () => { - await esArchiver.unload('x-pack/test/functional/es_archives/auditbeat/hosts'); + await esArchiver.unload(path); }); beforeEach(async () => { - await createSignalsIndex(supertest, log); + await createAlertsIndex(supertest, log); }); afterEach(async () => { @@ -377,9 +373,9 @@ export default ({ getService }: FtrProviderContext) => { * * ref: https://github.com/elastic/elasticsearch/issues/28806#issuecomment-369303620 */ - it('should generate 200 signals when timestamp override does not exist', async () => { + it('should generate 200 alerts when timestamp override does not exist', async () => { const rule: QueryRuleCreateProps = { - ...getRuleForSignalTesting(['auditbeat-*']), + ...getRuleForAlertTesting(['auditbeat-*']), timestamp_override: 'event.fakeingested', max_signals: 200, }; @@ -390,11 +386,11 @@ export default ({ getService }: FtrProviderContext) => { log, id, }); - await waitForSignalsToBePresent(supertest, log, 200, [id]); - const signalsResponse = await getSignalsByIds(supertest, log, [id], 200); - const signals = signalsResponse.hits.hits.map((hit) => hit._source); + await waitForAlertsToBePresent(supertest, log, 200, [id]); + const alertsResponse = await getAlertsByIds(supertest, log, [id], 200); + const alerts = alertsResponse.hits.hits.map((hit) => hit._source); - expect(signals.length).equal(200); + expect(alerts.length).equal(200); }); }); }); diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/group4/telemetry/README.md b/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/telemetry/README.md similarity index 100% rename from x-pack/test/detection_engine_api_integration/security_and_spaces/group4/telemetry/README.md rename to x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/telemetry/README.md diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/rule_execution_logic/config.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/telemetry/configs/ess.config.ts similarity index 63% rename from x-pack/test/detection_engine_api_integration/security_and_spaces/rule_execution_logic/config.ts rename to x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/telemetry/configs/ess.config.ts index 2430b8f2148d9..787542036e084 100644 --- a/x-pack/test/detection_engine_api_integration/security_and_spaces/rule_execution_logic/config.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/telemetry/configs/ess.config.ts @@ -7,12 +7,16 @@ import { FtrConfigProviderContext } from '@kbn/test'; -// eslint-disable-next-line import/no-default-export export default async function ({ readConfigFile }: FtrConfigProviderContext) { - const functionalConfig = await readConfigFile(require.resolve('../config.base.ts')); + const functionalConfig = await readConfigFile( + require.resolve('../../../../../config/ess/config.base.trial') + ); return { ...functionalConfig.getAll(), - testFiles: [require.resolve('.')], + testFiles: [require.resolve('..')], + junit: { + reportName: 'Detection Engine API Integration Tests - ESS - Telemetry', + }, }; } diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/telemetry/configs/serverless.config.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/telemetry/configs/serverless.config.ts new file mode 100644 index 0000000000000..99bd2458c69a4 --- /dev/null +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/telemetry/configs/serverless.config.ts @@ -0,0 +1,18 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { createTestConfig } from '../../../../../config/serverless/config.base'; + +export default createTestConfig({ + testFiles: [require.resolve('..')], + junit: { + reportName: 'Detection Engine API Integration Tests - Serverless - Telemetry', + }, + kbnTestServerArgs: [ + `--xpack.securitySolution.enableExperimental=${JSON.stringify(['previewTelemetryUrlEnabled'])}`, + ], +}); diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/group4/telemetry/index.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/telemetry/index.ts similarity index 83% rename from x-pack/test/detection_engine_api_integration/security_and_spaces/group4/telemetry/index.ts rename to x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/telemetry/index.ts index 4e180f73dc742..5fef7869ba7c8 100644 --- a/x-pack/test/detection_engine_api_integration/security_and_spaces/group4/telemetry/index.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/telemetry/index.ts @@ -4,15 +4,14 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ +import { FtrProviderContext } from '../../../../ftr_provider_context'; -import { FtrProviderContext } from '../../../common/ftr_provider_context'; - -// eslint-disable-next-line import/no-default-export export default ({ loadTestFile }: FtrProviderContext): void => { describe('Detection rule type telemetry', function () { loadTestFile(require.resolve('./usage_collector/all_types')); loadTestFile(require.resolve('./usage_collector/detection_rules')); loadTestFile(require.resolve('./usage_collector/detection_rule_status')); + loadTestFile(require.resolve('./usage_collector/detection_rules_legacy_action')); loadTestFile(require.resolve('./task_based/all_types')); loadTestFile(require.resolve('./task_based/detection_rules')); diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/group4/telemetry/task_based/all_types.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/telemetry/task_based/all_types.ts similarity index 82% rename from x-pack/test/detection_engine_api_integration/security_and_spaces/group4/telemetry/task_based/all_types.ts rename to x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/telemetry/task_based/all_types.ts index 576f00b563724..26ac4627a0260 100644 --- a/x-pack/test/detection_engine_api_integration/security_and_spaces/group4/telemetry/task_based/all_types.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/telemetry/task_based/all_types.ts @@ -6,17 +6,18 @@ */ import expect from '@kbn/expect'; -import { FtrProviderContext } from '../../../../common/ftr_provider_context'; + import { - createSignalsIndex, + createAlertsIndex, deleteAllRules, deleteAllAlerts, getSecurityTelemetryStats, removeTimeFieldsFromTelemetryStats, -} from '../../../../utils'; -import { deleteAllExceptions } from '../../../../../lists_api_integration/utils'; +} from '../../../utils'; +import { deleteAllExceptions } from '../../../../../../lists_api_integration/utils'; + +import { FtrProviderContext } from '../../../../../ftr_provider_context'; -// eslint-disable-next-line import/no-default-export export default ({ getService }: FtrProviderContext) => { const supertest = getService('supertest'); const esArchiver = getService('esArchiver'); @@ -24,7 +25,7 @@ export default ({ getService }: FtrProviderContext) => { const retry = getService('retry'); const es = getService('es'); - describe('All task telemetry types generically', async () => { + describe('@ess @serverless All task telemetry types generically', async () => { before(async () => { await esArchiver.load('x-pack/test/functional/es_archives/security_solution/telemetry'); }); @@ -34,7 +35,7 @@ export default ({ getService }: FtrProviderContext) => { }); beforeEach(async () => { - await createSignalsIndex(supertest, log); + await createAlertsIndex(supertest, log); }); afterEach(async () => { @@ -43,7 +44,7 @@ export default ({ getService }: FtrProviderContext) => { await deleteAllExceptions(supertest, log); }); - it('should only have task metric values when no rules are running', async () => { + it('@skipInQA should only have task metric values when no rules are running', async () => { await retry.try(async () => { const stats = await getSecurityTelemetryStats(supertest, log); removeTimeFieldsFromTelemetryStats(stats); diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/group4/telemetry/task_based/detection_rules.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/telemetry/task_based/detection_rules.ts similarity index 92% rename from x-pack/test/detection_engine_api_integration/security_and_spaces/group4/telemetry/task_based/detection_rules.ts rename to x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/telemetry/task_based/detection_rules.ts index 684fc752c152e..bed9457c34707 100644 --- a/x-pack/test/detection_engine_api_integration/security_and_spaces/group4/telemetry/task_based/detection_rules.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/telemetry/task_based/detection_rules.ts @@ -10,23 +10,22 @@ import expect from '@kbn/expect'; import { DETECTION_ENGINE_RULES_URL } from '@kbn/security-solution-plugin/common/constants'; import { ELASTIC_SECURITY_RULE_ID } from '@kbn/security-solution-plugin/common'; -import { FtrProviderContext } from '../../../../common/ftr_provider_context'; import { createRule, - createSignalsIndex, + createAlertsIndex, deleteAllRules, deleteAllAlerts, - getRule, - getRuleForSignalTesting, + fetchRule, + getRuleForAlertTesting, installMockPrebuiltRules, getSecurityTelemetryStats, createExceptionList, createExceptionListItem, removeTimeFieldsFromTelemetryStats, -} from '../../../../utils'; -import { deleteAllExceptions } from '../../../../../lists_api_integration/utils'; +} from '../../../utils'; +import { deleteAllExceptions } from '../../../../../../lists_api_integration/utils'; +import { FtrProviderContext } from '../../../../../ftr_provider_context'; -// eslint-disable-next-line import/no-default-export export default ({ getService }: FtrProviderContext) => { const es = getService('es'); const supertest = getService('supertest'); @@ -34,7 +33,7 @@ export default ({ getService }: FtrProviderContext) => { const log = getService('log'); const retry = getService('retry'); - describe('Detection rule task telemetry', async () => { + describe('@ess @serverless Detection rule task telemetry', async () => { before(async () => { await esArchiver.load('x-pack/test/functional/es_archives/security_solution/telemetry'); }); @@ -44,7 +43,7 @@ export default ({ getService }: FtrProviderContext) => { }); beforeEach(async () => { - await createSignalsIndex(supertest, log); + await createAlertsIndex(supertest, log); }); afterEach(async () => { @@ -54,8 +53,8 @@ export default ({ getService }: FtrProviderContext) => { }); describe('custom rules should never show any detection_rules telemetry data for each list type', () => { - it('should NOT give telemetry/stats for an exception list of type "detection"', async () => { - const rule = getRuleForSignalTesting(['telemetry'], 'rule-1', false); + it('@skipInQA should NOT give telemetry/stats for an exception list of type "detection"', async () => { + const rule = getRuleForAlertTesting(['telemetry'], 'rule-1', false); // create an exception list container of type "detection" const { id, list_id, namespace_type, type } = await createExceptionList(supertest, log, { @@ -110,8 +109,8 @@ export default ({ getService }: FtrProviderContext) => { }); }); - it('should NOT give telemetry/stats for an exception list of type "endpoint"', async () => { - const rule = getRuleForSignalTesting(['telemetry'], 'rule-1', false); + it('@skipInQA should NOT give telemetry/stats for an exception list of type "endpoint"', async () => { + const rule = getRuleForAlertTesting(['telemetry'], 'rule-1', false); // create an exception list container of type "detection" const { id, list_id, namespace_type, type } = await createExceptionList(supertest, log, { @@ -166,8 +165,8 @@ export default ({ getService }: FtrProviderContext) => { }); }); - it('should NOT give telemetry/stats for an exception list of type "endpoint_trusted_apps"', async () => { - const rule = getRuleForSignalTesting(['telemetry'], 'rule-1', false); + it('@skipInQA should NOT give telemetry/stats for an exception list of type "endpoint_trusted_apps"', async () => { + const rule = getRuleForAlertTesting(['telemetry'], 'rule-1', false); // create an exception list container of type "detection" const { id, list_id, namespace_type, type } = await createExceptionList(supertest, log, { @@ -222,8 +221,8 @@ export default ({ getService }: FtrProviderContext) => { }); }); - it('should NOT give telemetry/stats for an exception list of type "endpoint_events"', async () => { - const rule = getRuleForSignalTesting(['telemetry'], 'rule-1', false); + it('@skipInQA should NOT give telemetry/stats for an exception list of type "endpoint_events"', async () => { + const rule = getRuleForAlertTesting(['telemetry'], 'rule-1', false); // create an exception list container of type "detection" const { id, list_id, namespace_type, type } = await createExceptionList(supertest, log, { @@ -278,8 +277,8 @@ export default ({ getService }: FtrProviderContext) => { }); }); - it('should NOT give telemetry/stats for an exception list of type "endpoint_host_isolation_exceptions"', async () => { - const rule = getRuleForSignalTesting(['telemetry'], 'rule-1', false); + it('@skipInQA should NOT give telemetry/stats for an exception list of type "endpoint_host_isolation_exceptions"', async () => { + const rule = getRuleForAlertTesting(['telemetry'], 'rule-1', false); // create an exception list container of type "detection" const { id, list_id, namespace_type, type } = await createExceptionList(supertest, log, { @@ -335,7 +334,7 @@ export default ({ getService }: FtrProviderContext) => { }); }); - describe('pre-built/immutable/elastic rules should show detection_rules telemetry data for each list type', () => { + describe('@skipInQA pre-built/immutable/elastic rules should show detection_rules telemetry data for each list type', () => { beforeEach(async () => { // install prepackaged rules to get immutable rules for testing await installMockPrebuiltRules(supertest, es); @@ -368,7 +367,9 @@ export default ({ getService }: FtrProviderContext) => { }); // add the exception list to the pre-built/immutable/elastic rule using "PATCH" endpoint - const { exceptions_list } = await getRule(supertest, log, ELASTIC_SECURITY_RULE_ID); + const { exceptions_list } = await fetchRule(supertest, { + ruleId: ELASTIC_SECURITY_RULE_ID, + }); await supertest .patch(DETECTION_ENGINE_RULES_URL) .set('kbn-xsrf', 'true') @@ -427,7 +428,7 @@ export default ({ getService }: FtrProviderContext) => { }); // add the exception list to the pre-built/immutable/elastic rule - const immutableRule = await getRule(supertest, log, ELASTIC_SECURITY_RULE_ID); + const immutableRule = await fetchRule(supertest, { ruleId: ELASTIC_SECURITY_RULE_ID }); await supertest .patch(DETECTION_ENGINE_RULES_URL) .set('kbn-xsrf', 'true') @@ -504,7 +505,7 @@ export default ({ getService }: FtrProviderContext) => { }); // add the exception list to the pre-built/immutable/elastic rule - const immutableRule = await getRule(supertest, log, ELASTIC_SECURITY_RULE_ID); + const immutableRule = await fetchRule(supertest, { ruleId: ELASTIC_SECURITY_RULE_ID }); await supertest .patch(DETECTION_ENGINE_RULES_URL) .set('kbn-xsrf', 'true') @@ -581,7 +582,7 @@ export default ({ getService }: FtrProviderContext) => { }); // add the exception list to the pre-built/immutable/elastic rule - const immutableRule = await getRule(supertest, log, ELASTIC_SECURITY_RULE_ID); + const immutableRule = await fetchRule(supertest, { ruleId: ELASTIC_SECURITY_RULE_ID }); await supertest .patch(DETECTION_ENGINE_RULES_URL) .set('kbn-xsrf', 'true') @@ -658,7 +659,7 @@ export default ({ getService }: FtrProviderContext) => { }); // add the exception list to the pre-built/immutable/elastic rule - const immutableRule = await getRule(supertest, log, ELASTIC_SECURITY_RULE_ID); + const immutableRule = await fetchRule(supertest, { ruleId: ELASTIC_SECURITY_RULE_ID }); await supertest .patch(DETECTION_ENGINE_RULES_URL) .set('kbn-xsrf', 'true') @@ -735,7 +736,7 @@ export default ({ getService }: FtrProviderContext) => { }); // add the exception list to the pre-built/immutable/elastic rule - const immutableRule = await getRule(supertest, log, ELASTIC_SECURITY_RULE_ID); + const immutableRule = await fetchRule(supertest, { ruleId: ELASTIC_SECURITY_RULE_ID }); await supertest .patch(DETECTION_ENGINE_RULES_URL) .set('kbn-xsrf', 'true') @@ -786,7 +787,7 @@ export default ({ getService }: FtrProviderContext) => { }); }); - describe('pre-built/immutable/elastic rules should show detection_rules telemetry data for multiple list items and types', () => { + describe('@skipInQA pre-built/immutable/elastic rules should show detection_rules telemetry data for multiple list items and types', () => { beforeEach(async () => { // install prepackaged rules to get immutable rules for testing await installMockPrebuiltRules(supertest, es); @@ -836,7 +837,7 @@ export default ({ getService }: FtrProviderContext) => { }); // add the exception list to the pre-built/immutable/elastic rule - const immutableRule = await getRule(supertest, log, ELASTIC_SECURITY_RULE_ID); + const immutableRule = await fetchRule(supertest, { ruleId: ELASTIC_SECURITY_RULE_ID }); await supertest .patch(DETECTION_ENGINE_RULES_URL) .set('kbn-xsrf', 'true') diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/group4/telemetry/task_based/security_lists.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/telemetry/task_based/security_lists.ts similarity index 97% rename from x-pack/test/detection_engine_api_integration/security_and_spaces/group4/telemetry/task_based/security_lists.ts rename to x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/telemetry/task_based/security_lists.ts index 50661a537472d..d654cba35902f 100644 --- a/x-pack/test/detection_engine_api_integration/security_and_spaces/group4/telemetry/task_based/security_lists.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/telemetry/task_based/security_lists.ts @@ -11,19 +11,18 @@ import { ENDPOINT_LIST_ID, ENDPOINT_TRUSTED_APPS_LIST_ID, } from '@kbn/securitysolution-list-constants'; -import { FtrProviderContext } from '../../../../common/ftr_provider_context'; import { - createSignalsIndex, + createAlertsIndex, deleteAllRules, deleteAllAlerts, getSecurityTelemetryStats, createExceptionListItem, createExceptionList, removeTimeFieldsFromTelemetryStats, -} from '../../../../utils'; -import { deleteAllExceptions } from '../../../../../lists_api_integration/utils'; +} from '../../../utils'; +import { deleteAllExceptions } from '../../../../../../lists_api_integration/utils'; +import { FtrProviderContext } from '../../../../../ftr_provider_context'; -// eslint-disable-next-line import/no-default-export export default ({ getService }: FtrProviderContext) => { const supertest = getService('supertest'); const esArchiver = getService('esArchiver'); @@ -32,7 +31,7 @@ export default ({ getService }: FtrProviderContext) => { const es = getService('es'); // Failing: See https://github.com/elastic/kibana/issues/164334 - describe.skip('Security lists task telemetry', async () => { + describe.skip('@ess @serverless Security lists task telemetry', async () => { before(async () => { await esArchiver.load('x-pack/test/functional/es_archives/security_solution/telemetry'); }); @@ -42,7 +41,7 @@ export default ({ getService }: FtrProviderContext) => { }); beforeEach(async () => { - await createSignalsIndex(supertest, log); + await createAlertsIndex(supertest, log); // Calling stats endpoint once like this guarantees that the trusted applications and exceptions lists are created for us. await getSecurityTelemetryStats(supertest, log); }); diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/group4/telemetry/usage_collector/all_types.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/telemetry/usage_collector/all_types.ts similarity index 80% rename from x-pack/test/detection_engine_api_integration/security_and_spaces/group4/telemetry/usage_collector/all_types.ts rename to x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/telemetry/usage_collector/all_types.ts index 503fcc3c1a5da..93e16cefa19ff 100644 --- a/x-pack/test/detection_engine_api_integration/security_and_spaces/group4/telemetry/usage_collector/all_types.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/telemetry/usage_collector/all_types.ts @@ -7,10 +7,10 @@ import expect from '@kbn/expect'; import { getInitialDetectionMetrics } from '@kbn/security-solution-plugin/server/usage/detections/get_initial_usage'; -import type { FtrProviderContext } from '../../../../common/ftr_provider_context'; -import { createSignalsIndex, deleteAllRules, deleteAllAlerts, getStats } from '../../../../utils'; -// eslint-disable-next-line import/no-default-export +import { createAlertsIndex, deleteAllRules, deleteAllAlerts, getStats } from '../../../utils'; +import { FtrProviderContext } from '../../../../../ftr_provider_context'; + export default ({ getService }: FtrProviderContext) => { const supertest = getService('supertest'); const esArchiver = getService('esArchiver'); @@ -18,7 +18,7 @@ export default ({ getService }: FtrProviderContext) => { const retry = getService('retry'); const es = getService('es'); - describe('Detection rule telemetry', async () => { + describe('@ess @serverless @skipInQA Detection rule telemetry', async () => { before(async () => { await esArchiver.load('x-pack/test/functional/es_archives/security_solution/telemetry'); }); @@ -28,7 +28,7 @@ export default ({ getService }: FtrProviderContext) => { }); beforeEach(async () => { - await createSignalsIndex(supertest, log); + await createAlertsIndex(supertest, log); }); afterEach(async () => { diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/group4/telemetry/usage_collector/detection_rule_status.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/telemetry/usage_collector/detection_rule_status.ts similarity index 96% rename from x-pack/test/detection_engine_api_integration/security_and_spaces/group4/telemetry/usage_collector/detection_rule_status.ts rename to x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/telemetry/usage_collector/detection_rule_status.ts index 233244ff5a05d..fc99c5f73ee5f 100644 --- a/x-pack/test/detection_engine_api_integration/security_and_spaces/group4/telemetry/usage_collector/detection_rule_status.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/telemetry/usage_collector/detection_rule_status.ts @@ -22,21 +22,20 @@ import { } from '@kbn/security-solution-plugin/server/usage/detections/rules/get_initial_usage'; import { createRule, - createSignalsIndex, + createAlertsIndex, deleteAllRules, deleteAllAlerts, - getEqlRuleForSignalTesting, - getRuleForSignalTesting, + getEqlRuleForAlertTesting, + getRuleForAlertTesting, getSimpleThreatMatch, getStats, - getThresholdRuleForSignalTesting, + getThresholdRuleForAlertTesting, waitForRuleSuccess, - waitForSignalsToBePresent, + waitForAlertsToBePresent, deleteAllEventLogExecutionEvents, -} from '../../../../utils'; -import type { FtrProviderContext } from '../../../../common/ftr_provider_context'; +} from '../../../utils'; +import { FtrProviderContext } from '../../../../../ftr_provider_context'; -// eslint-disable-next-line import/no-default-export export default ({ getService }: FtrProviderContext) => { const supertest = getService('supertest'); const esArchiver = getService('esArchiver'); @@ -46,7 +45,7 @@ export default ({ getService }: FtrProviderContext) => { // Note: We don't actually find signals well with ML tests at the moment so there are not tests for ML rule type for telemetry // FAILING ES PROMOTION: https://github.com/elastic/kibana/issues/132856 - describe('Detection rule status telemetry', async () => { + describe('@ess @serverless Detection rule status telemetry', async () => { before(async () => { // Just in case other tests do not clean up the event logs, let us clear them now and here only once. await deleteAllEventLogExecutionEvents(es, log); @@ -58,7 +57,7 @@ export default ({ getService }: FtrProviderContext) => { }); beforeEach(async () => { - await createSignalsIndex(supertest, log); + await createAlertsIndex(supertest, log); }); afterEach(async () => { @@ -67,13 +66,14 @@ export default ({ getService }: FtrProviderContext) => { await deleteAllEventLogExecutionEvents(es, log); }); - describe('"kql" rule type', () => { + // FLAKY: https://github.com/elastic/kibana/issues/171438 + describe.skip('"kql" rule type', () => { let stats: DetectionMetrics | undefined; before(async () => { - const rule = getRuleForSignalTesting(['telemetry']); + const rule = getRuleForAlertTesting(['telemetry']); const { id } = await createRule(supertest, log, rule); await waitForRuleSuccess({ supertest, log, id }); - await waitForSignalsToBePresent(supertest, log, 4, [id]); + await waitForAlertsToBePresent(supertest, log, 4, [id]); // get the stats for all the tests where we at least have the expected "query" to reduce chances of flake by checking that at least one custom rule passed await retry.try(async () => { stats = await getStats(supertest, log); @@ -120,7 +120,7 @@ export default ({ getService }: FtrProviderContext) => { expect(stats?.detection_rules.detection_rule_usage).to.eql(expectedRuleUsage); }); - it('should have zero values for "detection_rule_status.all_rules" rules that are not query based', () => { + it('@skipInQA should have zero values for "detection_rule_status.all_rules" rules that are not query based', () => { expect(stats?.detection_rules.detection_rule_status.all_rules.eql).to.eql( getInitialSingleEventMetric() ); @@ -172,7 +172,7 @@ export default ({ getService }: FtrProviderContext) => { ); }); - it('should have non zero values for "index_duration"', () => { + it('@skipInQA should have non zero values for "index_duration"', () => { expect( stats?.detection_rules.detection_rule_status.custom_rules.query.index_duration.max ).to.be.above(1); @@ -205,11 +205,11 @@ export default ({ getService }: FtrProviderContext) => { ).to.be.above(1); }); - it('should have non zero values for "succeeded"', () => { + it('@skipInQA should have non zero values for "succeeded"', () => { expect(stats?.detection_rules.detection_rule_status.custom_rules.query.succeeded).to.eql(1); }); - it('should have non zero values for "succeeded", "index_duration", "search_duration" and "enrichment_duration"', () => { + it('@skipInQA should have non zero values for "succeeded", "index_duration", "search_duration" and "enrichment_duration"', () => { expect( stats?.detection_rules.detection_rule_status.custom_rules.query.index_duration.max ).to.be.above(1); @@ -257,10 +257,10 @@ export default ({ getService }: FtrProviderContext) => { describe('"eql" rule type', () => { let stats: DetectionMetrics | undefined; before(async () => { - const rule = getEqlRuleForSignalTesting(['telemetry']); + const rule = getEqlRuleForAlertTesting(['telemetry']); const { id } = await createRule(supertest, log, rule); await waitForRuleSuccess({ supertest, log, id }); - await waitForSignalsToBePresent(supertest, log, 4, [id]); + await waitForAlertsToBePresent(supertest, log, 4, [id]); // get the stats for all the tests where we at least have the expected "query" to reduce chances of flake by checking that at least one custom rule passed await retry.try(async () => { stats = await getStats(supertest, log); @@ -445,7 +445,7 @@ export default ({ getService }: FtrProviderContext) => { let stats: DetectionMetrics | undefined; before(async () => { const rule: ThresholdRuleCreateProps = { - ...getThresholdRuleForSignalTesting(['telemetry']), + ...getThresholdRuleForAlertTesting(['telemetry']), threshold: { field: 'keyword', value: 1, @@ -453,7 +453,7 @@ export default ({ getService }: FtrProviderContext) => { }; const { id } = await createRule(supertest, log, rule); await waitForRuleSuccess({ supertest, log, id }); - await waitForSignalsToBePresent(supertest, log, 4, [id]); + await waitForAlertsToBePresent(supertest, log, 4, [id]); // get the stats for all the tests where we at least have the expected "query" to reduce chances of flake by checking that at least one custom rule passed await retry.try(async () => { stats = await getStats(supertest, log); @@ -662,7 +662,7 @@ export default ({ getService }: FtrProviderContext) => { }; const { id } = await createRule(supertest, log, rule); await waitForRuleSuccess({ supertest, log, id }); - await waitForSignalsToBePresent(supertest, log, 4, [id]); + await waitForAlertsToBePresent(supertest, log, 4, [id]); // get the stats for all the tests where we at least have the expected "query" to reduce chances of flake by checking that at least one custom rule passed await retry.try(async () => { stats = await getStats(supertest, log); diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/group4/telemetry/usage_collector/detection_rules.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/telemetry/usage_collector/detection_rules.ts similarity index 86% rename from x-pack/test/detection_engine_api_integration/security_and_spaces/group4/telemetry/usage_collector/detection_rules.ts rename to x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/telemetry/usage_collector/detection_rules.ts index 652d13fd32a53..b81ced41b2511 100644 --- a/x-pack/test/detection_engine_api_integration/security_and_spaces/group4/telemetry/usage_collector/detection_rules.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/telemetry/usage_collector/detection_rules.ts @@ -14,34 +14,34 @@ import type { import { getInitialDetectionMetrics } from '@kbn/security-solution-plugin/server/usage/detections/get_initial_usage'; import { ELASTIC_SECURITY_RULE_ID } from '@kbn/security-solution-plugin/common'; import { RulesTypeUsage } from '@kbn/security-solution-plugin/server/usage/detections/rules/types'; -import type { FtrProviderContext } from '../../../../common/ftr_provider_context'; import { createLegacyRuleAction, - createNewAction, + createWebHookRuleAction, createRule, - createSignalsIndex, + createAlertsIndex, deleteAllRules, deleteAllAlerts, - getEqlRuleForSignalTesting, - getRule, - getRuleForSignalTesting, + getEqlRuleForAlertTesting, + fetchRule, + getRuleForAlertTesting, getRuleWithWebHookAction, getSimpleMlRule, getSimpleRule, getSimpleThreatMatch, getStats, - getThresholdRuleForSignalTesting, + getThresholdRuleForAlertTesting, installMockPrebuiltRules, waitForRuleSuccess, - waitForSignalsToBePresent, + waitForAlertsToBePresent, updateRule, deleteAllEventLogExecutionEvents, getRuleSavedObjectWithLegacyInvestigationFields, getRuleSavedObjectWithLegacyInvestigationFieldsEmptyArray, createRuleThroughAlertingEndpoint, -} from '../../../../utils'; +} from '../../../utils'; + +import { FtrProviderContext } from '../../../../../ftr_provider_context'; -// eslint-disable-next-line import/no-default-export export default ({ getService }: FtrProviderContext) => { const supertest = getService('supertest'); const esArchiver = getService('esArchiver'); @@ -49,7 +49,7 @@ export default ({ getService }: FtrProviderContext) => { const retry = getService('retry'); const es = getService('es'); - describe('Detection rule telemetry', async () => { + describe('@ess @serverless Detection rule telemetry', async () => { before(async () => { // Just in case other tests do not clean up the event logs, let us clear them now and here only once. await deleteAllEventLogExecutionEvents(es, log); @@ -61,7 +61,7 @@ export default ({ getService }: FtrProviderContext) => { }); beforeEach(async () => { - await createSignalsIndex(supertest, log); + await createAlertsIndex(supertest, log); }); afterEach(async () => { @@ -72,7 +72,7 @@ export default ({ getService }: FtrProviderContext) => { describe('"kql" rule type', () => { it('should show "notifications_enabled", "notifications_disabled" "legacy_notifications_enabled", "legacy_notifications_disabled", all to be "0" for "disabled"/"in-active" rule that does not have any actions', async () => { - const rule = getRuleForSignalTesting(['telemetry'], 'rule-1', false); + const rule = getRuleForAlertTesting(['telemetry'], 'rule-1', false); await createRule(supertest, log, rule); await retry.try(async () => { const stats = await getStats(supertest, log); @@ -102,10 +102,10 @@ export default ({ getService }: FtrProviderContext) => { }); it('should show "notifications_enabled", "notifications_disabled" "legacy_notifications_enabled", "legacy_notifications_disabled", all to be "0" for "enabled"/"active" rule that does not have any actions', async () => { - const rule = getRuleForSignalTesting(['telemetry']); + const rule = getRuleForAlertTesting(['telemetry']); const { id } = await createRule(supertest, log, rule); await waitForRuleSuccess({ supertest, log, id }); - await waitForSignalsToBePresent(supertest, log, 4, [id]); + await waitForAlertsToBePresent(supertest, log, 4, [id]); await retry.try(async () => { const stats = await getStats(supertest, log); const expected: RulesTypeUsage = { @@ -136,8 +136,8 @@ export default ({ getService }: FtrProviderContext) => { }); it('should show "notifications_disabled" to be "1" for rule that has at least "1" action(s) and the alert is "disabled"/"in-active"', async () => { - const rule = getRuleForSignalTesting(['telemetry']); - const hookAction = await createNewAction(supertest, log); + const rule = getRuleForAlertTesting(['telemetry']); + const hookAction = await createWebHookRuleAction(supertest); const ruleToCreate = getRuleWithWebHookAction(hookAction.id, false, rule); await createRule(supertest, log, ruleToCreate); @@ -160,13 +160,13 @@ export default ({ getService }: FtrProviderContext) => { }); }); - it('should show "notifications_enabled" to be "1" for rule that has at least "1" action(s) and the alert is "enabled"/"active"', async () => { - const rule = getRuleForSignalTesting(['telemetry']); - const hookAction = await createNewAction(supertest, log); + it('@brokenInServerless should show "notifications_enabled" to be "1" for rule that has at least "1" action(s) and the alert is "enabled"/"active"', async () => { + const rule = getRuleForAlertTesting(['telemetry']); + const hookAction = await createWebHookRuleAction(supertest); const ruleToCreate = getRuleWithWebHookAction(hookAction.id, true, rule); const { id } = await createRule(supertest, log, ruleToCreate); await waitForRuleSuccess({ supertest, log, id }); - await waitForSignalsToBePresent(supertest, log, 4, [id]); + await waitForAlertsToBePresent(supertest, log, 4, [id]); await retry.try(async () => { const stats = await getStats(supertest, log); @@ -189,10 +189,10 @@ export default ({ getService }: FtrProviderContext) => { }); }); - it('should show "legacy_notifications_disabled" to be "1" for rule that has at least "1" legacy action(s) and the alert is "disabled"/"in-active"', async () => { - const rule = getRuleForSignalTesting(['telemetry'], 'rule-1', false); + it('@brokenInServerless should show "legacy_notifications_disabled" to be "1" for rule that has at least "1" legacy action(s) and the alert is "disabled"/"in-active"', async () => { + const rule = getRuleForAlertTesting(['telemetry'], 'rule-1', false); const { id } = await createRule(supertest, log, rule); - const hookAction = await createNewAction(supertest, log); + const hookAction = await createWebHookRuleAction(supertest); await createLegacyRuleAction(supertest, id, hookAction.id); await retry.try(async () => { @@ -215,13 +215,13 @@ export default ({ getService }: FtrProviderContext) => { }); }); - it('should show "legacy_notifications_enabled" to be "1" for rule that has at least "1" legacy action(s) and the alert is "enabled"/"active"', async () => { - const rule = getRuleForSignalTesting(['telemetry']); + it('@brokenInServerless should show "legacy_notifications_enabled" to be "1" for rule that has at least "1" legacy action(s) and the alert is "enabled"/"active"', async () => { + const rule = getRuleForAlertTesting(['telemetry']); const { id } = await createRule(supertest, log, rule); - const hookAction = await createNewAction(supertest, log); + const hookAction = await createWebHookRuleAction(supertest); await createLegacyRuleAction(supertest, id, hookAction.id); await waitForRuleSuccess({ supertest, log, id }); - await waitForSignalsToBePresent(supertest, log, 4, [id]); + await waitForAlertsToBePresent(supertest, log, 4, [id]); await retry.try(async () => { const stats = await getStats(supertest, log); @@ -244,7 +244,7 @@ export default ({ getService }: FtrProviderContext) => { }); }); - describe('legacy investigation fields', () => { + describe('@brokenInServerless legacy investigation fields', () => { beforeEach(async () => { await deleteAllRules(supertest, log); await createRuleThroughAlertingEndpoint( @@ -294,7 +294,7 @@ export default ({ getService }: FtrProviderContext) => { describe('"eql" rule type', () => { it('should show "notifications_enabled", "notifications_disabled" "legacy_notifications_enabled", "legacy_notifications_disabled", all to be "0" for "disabled"/"in-active" rule that does not have any actions', async () => { - const rule = getEqlRuleForSignalTesting(['telemetry'], 'rule-1', false); + const rule = getEqlRuleForAlertTesting(['telemetry'], 'rule-1', false); await createRule(supertest, log, rule); await retry.try(async () => { const stats = await getStats(supertest, log); @@ -322,10 +322,10 @@ export default ({ getService }: FtrProviderContext) => { }); it('should show "notifications_enabled", "notifications_disabled" "legacy_notifications_enabled", "legacy_notifications_disabled", all to be "0" for "enabled"/"active" rule that does not have any actions', async () => { - const rule = getEqlRuleForSignalTesting(['telemetry']); + const rule = getEqlRuleForAlertTesting(['telemetry']); const { id } = await createRule(supertest, log, rule); await waitForRuleSuccess({ supertest, log, id }); - await waitForSignalsToBePresent(supertest, log, 4, [id]); + await waitForAlertsToBePresent(supertest, log, 4, [id]); await retry.try(async () => { const stats = await getStats(supertest, log); const expected: RulesTypeUsage = { @@ -356,8 +356,8 @@ export default ({ getService }: FtrProviderContext) => { }); it('should show "notifications_disabled" to be "1" for rule that has at least "1" action(s) and the alert is "disabled"/"in-active"', async () => { - const rule = getEqlRuleForSignalTesting(['telemetry']); - const hookAction = await createNewAction(supertest, log); + const rule = getEqlRuleForAlertTesting(['telemetry']); + const hookAction = await createWebHookRuleAction(supertest); const ruleToCreate = getRuleWithWebHookAction(hookAction.id, false, rule); await createRule(supertest, log, ruleToCreate); @@ -381,12 +381,12 @@ export default ({ getService }: FtrProviderContext) => { }); it('should show "notifications_enabled" to be "1" for rule that has at least "1" action(s) and the alert is "enabled"/"active"', async () => { - const rule = getEqlRuleForSignalTesting(['telemetry']); - const hookAction = await createNewAction(supertest, log); + const rule = getEqlRuleForAlertTesting(['telemetry']); + const hookAction = await createWebHookRuleAction(supertest); const ruleToCreate = getRuleWithWebHookAction(hookAction.id, true, rule); const { id } = await createRule(supertest, log, ruleToCreate); await waitForRuleSuccess({ supertest, log, id }); - await waitForSignalsToBePresent(supertest, log, 4, [id]); + await waitForAlertsToBePresent(supertest, log, 4, [id]); await retry.try(async () => { const stats = await getStats(supertest, log); @@ -409,10 +409,10 @@ export default ({ getService }: FtrProviderContext) => { }); }); - it('should show "legacy_notifications_disabled" to be "1" for rule that has at least "1" legacy action(s) and the alert is "disabled"/"in-active"', async () => { - const rule = getEqlRuleForSignalTesting(['telemetry'], 'rule-1', false); + it('@brokenInServerless should show "legacy_notifications_disabled" to be "1" for rule that has at least "1" legacy action(s) and the alert is "disabled"/"in-active"', async () => { + const rule = getEqlRuleForAlertTesting(['telemetry'], 'rule-1', false); const { id } = await createRule(supertest, log, rule); - const hookAction = await createNewAction(supertest, log); + const hookAction = await createWebHookRuleAction(supertest); await createLegacyRuleAction(supertest, id, hookAction.id); await retry.try(async () => { @@ -434,13 +434,13 @@ export default ({ getService }: FtrProviderContext) => { }); }); - it('should show "legacy_notifications_enabled" to be "1" for rule that has at least "1" legacy action(s) and the alert is "enabled"/"active"', async () => { - const rule = getEqlRuleForSignalTesting(['telemetry']); + it('@brokenInServerless should show "legacy_notifications_enabled" to be "1" for rule that has at least "1" legacy action(s) and the alert is "enabled"/"active"', async () => { + const rule = getEqlRuleForAlertTesting(['telemetry']); const { id } = await createRule(supertest, log, rule); - const hookAction = await createNewAction(supertest, log); + const hookAction = await createWebHookRuleAction(supertest); await createLegacyRuleAction(supertest, id, hookAction.id); await waitForRuleSuccess({ supertest, log, id }); - await waitForSignalsToBePresent(supertest, log, 4, [id]); + await waitForAlertsToBePresent(supertest, log, 4, [id]); await retry.try(async () => { const stats = await getStats(supertest, log); @@ -467,7 +467,7 @@ export default ({ getService }: FtrProviderContext) => { describe('"threshold" rule type', () => { it('should show "notifications_enabled", "notifications_disabled" "legacy_notifications_enabled", "legacy_notifications_disabled", all to be "0" for "disabled"/"in-active" rule that does not have any actions', async () => { const rule: ThresholdRuleCreateProps = { - ...getThresholdRuleForSignalTesting(['telemetry'], 'rule-1', false), + ...getThresholdRuleForAlertTesting(['telemetry'], 'rule-1', false), threshold: { field: 'keyword', value: 1, @@ -503,7 +503,7 @@ export default ({ getService }: FtrProviderContext) => { it('should show "notifications_enabled", "notifications_disabled" "legacy_notifications_enabled", "legacy_notifications_disabled", all to be "0" for "enabled"/"active" rule that does not have any actions', async () => { const rule: ThresholdRuleCreateProps = { - ...getThresholdRuleForSignalTesting(['telemetry']), + ...getThresholdRuleForAlertTesting(['telemetry']), threshold: { field: 'keyword', value: 1, @@ -511,7 +511,7 @@ export default ({ getService }: FtrProviderContext) => { }; const { id } = await createRule(supertest, log, rule); await waitForRuleSuccess({ supertest, log, id }); - await waitForSignalsToBePresent(supertest, log, 4, [id]); + await waitForAlertsToBePresent(supertest, log, 4, [id]); await retry.try(async () => { const stats = await getStats(supertest, log); const expected: RulesTypeUsage = { @@ -543,13 +543,13 @@ export default ({ getService }: FtrProviderContext) => { it('should show "notifications_disabled" to be "1" for rule that has at least "1" action(s) and the alert is "disabled"/"in-active"', async () => { const rule: ThresholdRuleCreateProps = { - ...getThresholdRuleForSignalTesting(['telemetry'], 'rule-1', false), + ...getThresholdRuleForAlertTesting(['telemetry'], 'rule-1', false), threshold: { field: 'keyword', value: 1, }, }; - const hookAction = await createNewAction(supertest, log); + const hookAction = await createWebHookRuleAction(supertest); const ruleToCreate = getRuleWithWebHookAction(hookAction.id, false, rule); await createRule(supertest, log, ruleToCreate); @@ -574,17 +574,17 @@ export default ({ getService }: FtrProviderContext) => { it('should show "notifications_enabled" to be "1" for rule that has at least "1" action(s) and the alert is "enabled"/"active"', async () => { const rule: ThresholdRuleCreateProps = { - ...getThresholdRuleForSignalTesting(['telemetry']), + ...getThresholdRuleForAlertTesting(['telemetry']), threshold: { field: 'keyword', value: 1, }, }; - const hookAction = await createNewAction(supertest, log); + const hookAction = await createWebHookRuleAction(supertest); const ruleToCreate = getRuleWithWebHookAction(hookAction.id, true, rule); const { id } = await createRule(supertest, log, ruleToCreate); await waitForRuleSuccess({ supertest, log, id }); - await waitForSignalsToBePresent(supertest, log, 4, [id]); + await waitForAlertsToBePresent(supertest, log, 4, [id]); await retry.try(async () => { const stats = await getStats(supertest, log); @@ -607,16 +607,16 @@ export default ({ getService }: FtrProviderContext) => { }); }); - it('should show "legacy_notifications_disabled" to be "1" for rule that has at least "1" legacy action(s) and the alert is "disabled"/"in-active"', async () => { + it('@brokenInServerless should show "legacy_notifications_disabled" to be "1" for rule that has at least "1" legacy action(s) and the alert is "disabled"/"in-active"', async () => { const rule: ThresholdRuleCreateProps = { - ...getThresholdRuleForSignalTesting(['telemetry'], 'rule-1', false), + ...getThresholdRuleForAlertTesting(['telemetry'], 'rule-1', false), threshold: { field: 'keyword', value: 1, }, }; const { id } = await createRule(supertest, log, rule); - const hookAction = await createNewAction(supertest, log); + const hookAction = await createWebHookRuleAction(supertest); await createLegacyRuleAction(supertest, id, hookAction.id); await retry.try(async () => { @@ -638,19 +638,19 @@ export default ({ getService }: FtrProviderContext) => { }); }); - it('should show "legacy_notifications_enabled" to be "1" for rule that has at least "1" legacy action(s) and the alert is "enabled"/"active"', async () => { + it('@brokenInServerless should show "legacy_notifications_enabled" to be "1" for rule that has at least "1" legacy action(s) and the alert is "enabled"/"active"', async () => { const rule: ThresholdRuleCreateProps = { - ...getThresholdRuleForSignalTesting(['telemetry']), + ...getThresholdRuleForAlertTesting(['telemetry']), threshold: { field: 'keyword', value: 1, }, }; const { id } = await createRule(supertest, log, rule); - const hookAction = await createNewAction(supertest, log); + const hookAction = await createWebHookRuleAction(supertest); await createLegacyRuleAction(supertest, id, hookAction.id); await waitForRuleSuccess({ supertest, log, id }); - await waitForSignalsToBePresent(supertest, log, 4, [id]); + await waitForAlertsToBePresent(supertest, log, 4, [id]); await retry.try(async () => { const stats = await getStats(supertest, log); @@ -738,7 +738,7 @@ export default ({ getService }: FtrProviderContext) => { it('should show "notifications_disabled" to be "1" for rule that has at least "1" action(s) and the alert is "disabled"/"in-active"', async () => { const rule = getSimpleMlRule(); - const hookAction = await createNewAction(supertest, log); + const hookAction = await createWebHookRuleAction(supertest); const ruleToCreate = getRuleWithWebHookAction(hookAction.id, false, rule); await createRule(supertest, log, ruleToCreate); @@ -763,7 +763,7 @@ export default ({ getService }: FtrProviderContext) => { it('should show "notifications_enabled" to be "1" for rule that has at least "1" action(s) and the alert is "enabled"/"active"', async () => { const rule = getSimpleMlRule('rule-1', true); - const hookAction = await createNewAction(supertest, log); + const hookAction = await createWebHookRuleAction(supertest); const ruleToCreate = getRuleWithWebHookAction(hookAction.id, true, rule); await createRule(supertest, log, ruleToCreate); @@ -786,10 +786,10 @@ export default ({ getService }: FtrProviderContext) => { }); }); - it('should show "legacy_notifications_disabled" to be "1" for rule that has at least "1" legacy action(s) and the alert is "disabled"/"in-active"', async () => { + it('@brokenInServerless should show "legacy_notifications_disabled" to be "1" for rule that has at least "1" legacy action(s) and the alert is "disabled"/"in-active"', async () => { const rule = getSimpleMlRule(); const { id } = await createRule(supertest, log, rule); - const hookAction = await createNewAction(supertest, log); + const hookAction = await createWebHookRuleAction(supertest); await createLegacyRuleAction(supertest, id, hookAction.id); await retry.try(async () => { @@ -811,10 +811,10 @@ export default ({ getService }: FtrProviderContext) => { }); }); - it('should show "legacy_notifications_enabled" to be "1" for rule that has at least "1" legacy action(s) and the alert is "enabled"/"active"', async () => { + it('@brokenInServerless should show "legacy_notifications_enabled" to be "1" for rule that has at least "1" legacy action(s) and the alert is "enabled"/"active"', async () => { const rule = getSimpleMlRule('rule-1', true); const { id } = await createRule(supertest, log, rule); - const hookAction = await createNewAction(supertest, log); + const hookAction = await createWebHookRuleAction(supertest); await createLegacyRuleAction(supertest, id, hookAction.id); await retry.try(async () => { @@ -887,7 +887,7 @@ export default ({ getService }: FtrProviderContext) => { }; const { id } = await createRule(supertest, log, rule); await waitForRuleSuccess({ supertest, log, id }); - await waitForSignalsToBePresent(supertest, log, 4, [id]); + await waitForAlertsToBePresent(supertest, log, 4, [id]); await retry.try(async () => { const stats = await getStats(supertest, log); const expected: RulesTypeUsage = { @@ -919,7 +919,7 @@ export default ({ getService }: FtrProviderContext) => { it('should show "notifications_disabled" to be "1" for rule that has at least "1" action(s) and the alert is "disabled"/"in-active"', async () => { const rule = getSimpleThreatMatch(); - const hookAction = await createNewAction(supertest, log); + const hookAction = await createWebHookRuleAction(supertest); const ruleToCreate = getRuleWithWebHookAction(hookAction.id, false, rule); await createRule(supertest, log, ruleToCreate); @@ -959,11 +959,11 @@ export default ({ getService }: FtrProviderContext) => { }, ], }; - const hookAction = await createNewAction(supertest, log); + const hookAction = await createWebHookRuleAction(supertest); const ruleToCreate = getRuleWithWebHookAction(hookAction.id, true, rule); const { id } = await createRule(supertest, log, ruleToCreate); await waitForRuleSuccess({ supertest, log, id }); - await waitForSignalsToBePresent(supertest, log, 4, [id]); + await waitForAlertsToBePresent(supertest, log, 4, [id]); await retry.try(async () => { const stats = await getStats(supertest, log); @@ -986,10 +986,10 @@ export default ({ getService }: FtrProviderContext) => { }); }); - it('should show "legacy_notifications_disabled" to be "1" for rule that has at least "1" legacy action(s) and the alert is "disabled"/"in-active"', async () => { + it('@brokenInServerless should show "legacy_notifications_disabled" to be "1" for rule that has at least "1" legacy action(s) and the alert is "disabled"/"in-active"', async () => { const rule = getSimpleThreatMatch(); const { id } = await createRule(supertest, log, rule); - const hookAction = await createNewAction(supertest, log); + const hookAction = await createWebHookRuleAction(supertest); await createLegacyRuleAction(supertest, id, hookAction.id); await retry.try(async () => { @@ -1011,7 +1011,7 @@ export default ({ getService }: FtrProviderContext) => { }); }); - it('should show "legacy_notifications_enabled" to be "1" for rule that has at least "1" legacy action(s) and the alert is "enabled"/"active"', async () => { + it('@brokenInServerless should show "legacy_notifications_enabled" to be "1" for rule that has at least "1" legacy action(s) and the alert is "enabled"/"active"', async () => { const rule: ThreatMatchRuleCreateProps = { ...getSimpleThreatMatch('rule-1', true), index: ['telemetry'], @@ -1029,10 +1029,10 @@ export default ({ getService }: FtrProviderContext) => { ], }; const { id } = await createRule(supertest, log, rule); - const hookAction = await createNewAction(supertest, log); + const hookAction = await createWebHookRuleAction(supertest); await createLegacyRuleAction(supertest, id, hookAction.id); await waitForRuleSuccess({ supertest, log, id }); - await waitForSignalsToBePresent(supertest, log, 4, [id]); + await waitForAlertsToBePresent(supertest, log, 4, [id]); await retry.try(async () => { const stats = await getStats(supertest, log); @@ -1057,7 +1057,7 @@ export default ({ getService }: FtrProviderContext) => { }); describe('"pre-packaged"/"immutable" rules', async () => { - it('should show stats for totals for in-active pre-packaged rules', async () => { + it('@skipInQA should show stats for totals for in-active pre-packaged rules', async () => { await installMockPrebuiltRules(supertest, es); await retry.try(async () => { const stats = await getStats(supertest, log); @@ -1090,7 +1090,7 @@ export default ({ getService }: FtrProviderContext) => { }); }); - it('should show stats for the detection_rule_details for a specific pre-packaged rule', async () => { + it('@skipInQA should show stats for the detection_rule_details for a specific pre-packaged rule', async () => { await installMockPrebuiltRules(supertest, es); await retry.try(async () => { const stats = await getStats(supertest, log); @@ -1121,13 +1121,13 @@ export default ({ getService }: FtrProviderContext) => { }); }); - it('should show "notifications_disabled" to be "1", "has_notification" to be "true, "has_legacy_notification" to be "false" for rule that has at least "1" action(s) and the alert is "disabled"/"in-active"', async () => { + it('@skipInQA should show "notifications_disabled" to be "1", "has_notification" to be "true, "has_legacy_notification" to be "false" for rule that has at least "1" action(s) and the alert is "disabled"/"in-active"', async () => { await installMockPrebuiltRules(supertest, es); - const immutableRule = await getRule(supertest, log, ELASTIC_SECURITY_RULE_ID); - const hookAction = await createNewAction(supertest, log); + const immutableRule = await fetchRule(supertest, { ruleId: ELASTIC_SECURITY_RULE_ID }); + const hookAction = await createWebHookRuleAction(supertest); const newRuleToUpdate = getSimpleRule(immutableRule.rule_id); const ruleToUpdate = getRuleWithWebHookAction(hookAction.id, false, newRuleToUpdate); - await updateRule(supertest, log, ruleToUpdate); + await updateRule(supertest, ruleToUpdate); await retry.try(async () => { const stats = await getStats(supertest, log); @@ -1174,13 +1174,13 @@ export default ({ getService }: FtrProviderContext) => { }); }); - it('should show "notifications_enabled" to be "1", "has_notification" to be "true, "has_legacy_notification" to be "false" for rule that has at least "1" action(s) and the alert is "enabled"/"active"', async () => { + it('@skipInQA should show "notifications_enabled" to be "1", "has_notification" to be "true, "has_legacy_notification" to be "false" for rule that has at least "1" action(s) and the alert is "enabled"/"active"', async () => { await installMockPrebuiltRules(supertest, es); - const immutableRule = await getRule(supertest, log, ELASTIC_SECURITY_RULE_ID); - const hookAction = await createNewAction(supertest, log); + const immutableRule = await fetchRule(supertest, { ruleId: ELASTIC_SECURITY_RULE_ID }); + const hookAction = await createWebHookRuleAction(supertest); const newRuleToUpdate = getSimpleRule(immutableRule.rule_id); const ruleToUpdate = getRuleWithWebHookAction(hookAction.id, true, newRuleToUpdate); - await updateRule(supertest, log, ruleToUpdate); + await updateRule(supertest, ruleToUpdate); await retry.try(async () => { const stats = await getStats(supertest, log); @@ -1227,12 +1227,12 @@ export default ({ getService }: FtrProviderContext) => { }); }); - it('should show "legacy_notifications_disabled" to be "1", "has_notification" to be "false, "has_legacy_notification" to be "true" for rule that has at least "1" action(s) and the alert is "disabled"/"in-active"', async () => { + it('@brokenInServerless should show "legacy_notifications_disabled" to be "1", "has_notification" to be "false, "has_legacy_notification" to be "true" for rule that has at least "1" action(s) and the alert is "disabled"/"in-active"', async () => { await installMockPrebuiltRules(supertest, es); - const immutableRule = await getRule(supertest, log, ELASTIC_SECURITY_RULE_ID); - const hookAction = await createNewAction(supertest, log); + const immutableRule = await fetchRule(supertest, { ruleId: ELASTIC_SECURITY_RULE_ID }); + const hookAction = await createWebHookRuleAction(supertest); const newRuleToUpdate = getSimpleRule(immutableRule.rule_id, false); - await updateRule(supertest, log, newRuleToUpdate); + await updateRule(supertest, newRuleToUpdate); await createLegacyRuleAction(supertest, immutableRule.id, hookAction.id); await retry.try(async () => { @@ -1280,12 +1280,12 @@ export default ({ getService }: FtrProviderContext) => { }); }); - it('should show "legacy_notifications_enabled" to be "1", "has_notification" to be "false, "has_legacy_notification" to be "true" for rule that has at least "1" action(s) and the alert is "enabled"/"active"', async () => { + it('@brokenInServerless should show "legacy_notifications_enabled" to be "1", "has_notification" to be "false, "has_legacy_notification" to be "true" for rule that has at least "1" action(s) and the alert is "enabled"/"active"', async () => { await installMockPrebuiltRules(supertest, es); - const immutableRule = await getRule(supertest, log, ELASTIC_SECURITY_RULE_ID); - const hookAction = await createNewAction(supertest, log); + const immutableRule = await fetchRule(supertest, { ruleId: ELASTIC_SECURITY_RULE_ID }); + const hookAction = await createWebHookRuleAction(supertest); const newRuleToUpdate = getSimpleRule(immutableRule.rule_id, true); - await updateRule(supertest, log, newRuleToUpdate); + await updateRule(supertest, newRuleToUpdate); await createLegacyRuleAction(supertest, immutableRule.id, hookAction.id); await retry.try(async () => { diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/telemetry/usage_collector/detection_rules_legacy_action.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/telemetry/usage_collector/detection_rules_legacy_action.ts new file mode 100644 index 0000000000000..b0e40253bb8c2 --- /dev/null +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/telemetry/usage_collector/detection_rules_legacy_action.ts @@ -0,0 +1,512 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license 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 { + ThreatMatchRuleCreateProps, + ThresholdRuleCreateProps, +} from '@kbn/security-solution-plugin/common/api/detection_engine'; +import { getInitialDetectionMetrics } from '@kbn/security-solution-plugin/server/usage/detections/get_initial_usage'; +import { ELASTIC_SECURITY_RULE_ID } from '@kbn/security-solution-plugin/common'; +import { RulesTypeUsage } from '@kbn/security-solution-plugin/server/usage/detections/rules/types'; +import { + createLegacyRuleAction, + createWebHookRuleAction, + createRule, + createAlertsIndex, + deleteAllRules, + deleteAllAlerts, + getEqlRuleForAlertTesting, + fetchRule, + getRuleForAlertTesting, + getRuleWithWebHookAction, + getSimpleMlRule, + getSimpleRule, + getSimpleThreatMatch, + getStats, + getThresholdRuleForAlertTesting, + installMockPrebuiltRules, + waitForRuleSuccess, + waitForAlertsToBePresent, + updateRule, + deleteAllEventLogExecutionEvents, +} from '../../../utils'; + +import { FtrProviderContext } from '../../../../../ftr_provider_context'; + +export default ({ getService }: FtrProviderContext) => { + const supertest = getService('supertest'); + const esArchiver = getService('esArchiver'); + const log = getService('log'); + const retry = getService('retry'); + const es = getService('es'); + + describe('@ess Detection rule legacy actions telemetry', async () => { + before(async () => { + // Just in case other tests do not clean up the event logs, let us clear them now and here only once. + await deleteAllEventLogExecutionEvents(es, log); + await esArchiver.load('x-pack/test/functional/es_archives/security_solution/telemetry'); + }); + + after(async () => { + await esArchiver.unload('x-pack/test/functional/es_archives/security_solution/telemetry'); + }); + + beforeEach(async () => { + await createAlertsIndex(supertest, log); + }); + + afterEach(async () => { + await deleteAllAlerts(supertest, log, es); + await deleteAllRules(supertest, log); + await deleteAllEventLogExecutionEvents(es, log); + }); + + describe('"kql" rule type', () => { + it('should show "notifications_enabled" to be "1" for rule that has at least "1" action(s) and the alert is "enabled"/"active"', async () => { + const rule = getRuleForAlertTesting(['telemetry']); + const hookAction = await createWebHookRuleAction(supertest); + const ruleToCreate = getRuleWithWebHookAction(hookAction.id, true, rule); + const { id } = await createRule(supertest, log, ruleToCreate); + await waitForRuleSuccess({ supertest, log, id }); + await waitForAlertsToBePresent(supertest, log, 4, [id]); + + await retry.try(async () => { + const stats = await getStats(supertest, log); + const expected: RulesTypeUsage = { + ...getInitialDetectionMetrics().detection_rules.detection_rule_usage, + query: { + ...getInitialDetectionMetrics().detection_rules.detection_rule_usage.query, + enabled: 1, + alerts: 4, + notifications_enabled: 1, + }, + custom_total: { + ...getInitialDetectionMetrics().detection_rules.detection_rule_usage.custom_total, + enabled: 1, + alerts: 4, + notifications_enabled: 1, + }, + }; + expect(stats.detection_rules.detection_rule_usage).to.eql(expected); + }); + }); + + it('should show "legacy_notifications_disabled" to be "1" for rule that has at least "1" legacy action(s) and the alert is "disabled"/"in-active"', async () => { + const rule = getRuleForAlertTesting(['telemetry'], 'rule-1', false); + const { id } = await createRule(supertest, log, rule); + const hookAction = await createWebHookRuleAction(supertest); + await createLegacyRuleAction(supertest, id, hookAction.id); + + await retry.try(async () => { + const stats = await getStats(supertest, log); + + const expected: RulesTypeUsage = { + ...getInitialDetectionMetrics().detection_rules.detection_rule_usage, + query: { + ...getInitialDetectionMetrics().detection_rules.detection_rule_usage.query, + disabled: 1, + legacy_notifications_disabled: 1, + }, + custom_total: { + ...getInitialDetectionMetrics().detection_rules.detection_rule_usage.custom_total, + disabled: 1, + legacy_notifications_disabled: 1, + }, + }; + expect(stats.detection_rules.detection_rule_usage).to.eql(expected); + }); + }); + + it('should show "legacy_notifications_enabled" to be "1" for rule that has at least "1" legacy action(s) and the alert is "enabled"/"active"', async () => { + const rule = getRuleForAlertTesting(['telemetry']); + const { id } = await createRule(supertest, log, rule); + const hookAction = await createWebHookRuleAction(supertest); + await createLegacyRuleAction(supertest, id, hookAction.id); + await waitForRuleSuccess({ supertest, log, id }); + await waitForAlertsToBePresent(supertest, log, 4, [id]); + + await retry.try(async () => { + const stats = await getStats(supertest, log); + const expected: RulesTypeUsage = { + ...getInitialDetectionMetrics().detection_rules.detection_rule_usage, + query: { + ...getInitialDetectionMetrics().detection_rules.detection_rule_usage.query, + alerts: 4, + enabled: 1, + legacy_notifications_enabled: 1, + }, + custom_total: { + ...getInitialDetectionMetrics().detection_rules.detection_rule_usage.custom_total, + alerts: 4, + enabled: 1, + legacy_notifications_enabled: 1, + }, + }; + expect(stats.detection_rules.detection_rule_usage).to.eql(expected); + }); + }); + }); + + describe('"eql" rule type', () => { + it('should show "legacy_notifications_disabled" to be "1" for rule that has at least "1" legacy action(s) and the alert is "disabled"/"in-active"', async () => { + const rule = getEqlRuleForAlertTesting(['telemetry'], 'rule-1', false); + const { id } = await createRule(supertest, log, rule); + const hookAction = await createWebHookRuleAction(supertest); + await createLegacyRuleAction(supertest, id, hookAction.id); + + await retry.try(async () => { + const stats = await getStats(supertest, log); + const expected: RulesTypeUsage = { + ...getInitialDetectionMetrics().detection_rules.detection_rule_usage, + eql: { + ...getInitialDetectionMetrics().detection_rules.detection_rule_usage.eql, + disabled: 1, + legacy_notifications_disabled: 1, + }, + custom_total: { + ...getInitialDetectionMetrics().detection_rules.detection_rule_usage.custom_total, + disabled: 1, + legacy_notifications_disabled: 1, + }, + }; + expect(stats.detection_rules.detection_rule_usage).to.eql(expected); + }); + }); + + it('should show "legacy_notifications_enabled" to be "1" for rule that has at least "1" legacy action(s) and the alert is "enabled"/"active"', async () => { + const rule = getEqlRuleForAlertTesting(['telemetry']); + const { id } = await createRule(supertest, log, rule); + const hookAction = await createWebHookRuleAction(supertest); + await createLegacyRuleAction(supertest, id, hookAction.id); + await waitForRuleSuccess({ supertest, log, id }); + await waitForAlertsToBePresent(supertest, log, 4, [id]); + + await retry.try(async () => { + const stats = await getStats(supertest, log); + const expected: RulesTypeUsage = { + ...getInitialDetectionMetrics().detection_rules.detection_rule_usage, + eql: { + ...getInitialDetectionMetrics().detection_rules.detection_rule_usage.eql, + alerts: 4, + enabled: 1, + legacy_notifications_enabled: 1, + }, + custom_total: { + ...getInitialDetectionMetrics().detection_rules.detection_rule_usage.custom_total, + alerts: 4, + enabled: 1, + legacy_notifications_enabled: 1, + }, + }; + expect(stats.detection_rules.detection_rule_usage).to.eql(expected); + }); + }); + }); + + describe('"threshold" rule type', () => { + it('should show "legacy_notifications_disabled" to be "1" for rule that has at least "1" legacy action(s) and the alert is "disabled"/"in-active"', async () => { + const rule: ThresholdRuleCreateProps = { + ...getThresholdRuleForAlertTesting(['telemetry'], 'rule-1', false), + threshold: { + field: 'keyword', + value: 1, + }, + }; + const { id } = await createRule(supertest, log, rule); + const hookAction = await createWebHookRuleAction(supertest); + await createLegacyRuleAction(supertest, id, hookAction.id); + + await retry.try(async () => { + const stats = await getStats(supertest, log); + const expected: RulesTypeUsage = { + ...getInitialDetectionMetrics().detection_rules.detection_rule_usage, + threshold: { + ...getInitialDetectionMetrics().detection_rules.detection_rule_usage.threshold, + disabled: 1, + legacy_notifications_disabled: 1, + }, + custom_total: { + ...getInitialDetectionMetrics().detection_rules.detection_rule_usage.custom_total, + disabled: 1, + legacy_notifications_disabled: 1, + }, + }; + expect(stats.detection_rules.detection_rule_usage).to.eql(expected); + }); + }); + + it('should show "legacy_notifications_enabled" to be "1" for rule that has at least "1" legacy action(s) and the alert is "enabled"/"active"', async () => { + const rule: ThresholdRuleCreateProps = { + ...getThresholdRuleForAlertTesting(['telemetry']), + threshold: { + field: 'keyword', + value: 1, + }, + }; + const { id } = await createRule(supertest, log, rule); + const hookAction = await createWebHookRuleAction(supertest); + await createLegacyRuleAction(supertest, id, hookAction.id); + await waitForRuleSuccess({ supertest, log, id }); + await waitForAlertsToBePresent(supertest, log, 4, [id]); + + await retry.try(async () => { + const stats = await getStats(supertest, log); + const expected: RulesTypeUsage = { + ...getInitialDetectionMetrics().detection_rules.detection_rule_usage, + threshold: { + ...getInitialDetectionMetrics().detection_rules.detection_rule_usage.threshold, + alerts: 4, + enabled: 1, + legacy_notifications_enabled: 1, + }, + custom_total: { + ...getInitialDetectionMetrics().detection_rules.detection_rule_usage.custom_total, + alerts: 4, + enabled: 1, + legacy_notifications_enabled: 1, + }, + }; + expect(stats.detection_rules.detection_rule_usage).to.eql(expected); + }); + }); + }); + + // Note: We don't actually find signals with these tests as we don't have a good way of signal finding with ML rules. + describe('"ml" rule type', () => { + it('should show "legacy_notifications_disabled" to be "1" for rule that has at least "1" legacy action(s) and the alert is "disabled"/"in-active"', async () => { + const rule = getSimpleMlRule(); + const { id } = await createRule(supertest, log, rule); + const hookAction = await createWebHookRuleAction(supertest); + await createLegacyRuleAction(supertest, id, hookAction.id); + + await retry.try(async () => { + const stats = await getStats(supertest, log); + const expected: RulesTypeUsage = { + ...getInitialDetectionMetrics().detection_rules.detection_rule_usage, + machine_learning: { + ...getInitialDetectionMetrics().detection_rules.detection_rule_usage.machine_learning, + disabled: 1, + legacy_notifications_disabled: 1, + }, + custom_total: { + ...getInitialDetectionMetrics().detection_rules.detection_rule_usage.custom_total, + disabled: 1, + legacy_notifications_disabled: 1, + }, + }; + expect(stats.detection_rules.detection_rule_usage).to.eql(expected); + }); + }); + + it('should show "legacy_notifications_enabled" to be "1" for rule that has at least "1" legacy action(s) and the alert is "enabled"/"active"', async () => { + const rule = getSimpleMlRule('rule-1', true); + const { id } = await createRule(supertest, log, rule); + const hookAction = await createWebHookRuleAction(supertest); + await createLegacyRuleAction(supertest, id, hookAction.id); + + await retry.try(async () => { + const stats = await getStats(supertest, log); + const expected: RulesTypeUsage = { + ...getInitialDetectionMetrics().detection_rules.detection_rule_usage, + machine_learning: { + ...getInitialDetectionMetrics().detection_rules.detection_rule_usage.machine_learning, + enabled: 1, + legacy_notifications_enabled: 1, + }, + custom_total: { + ...getInitialDetectionMetrics().detection_rules.detection_rule_usage.custom_total, + enabled: 1, + legacy_notifications_enabled: 1, + }, + }; + expect(stats.detection_rules.detection_rule_usage).to.eql(expected); + }); + }); + }); + + describe('"indicator_match/threat_match" rule type', () => { + it('should show "legacy_notifications_disabled" to be "1" for rule that has at least "1" legacy action(s) and the alert is "disabled"/"in-active"', async () => { + const rule = getSimpleThreatMatch(); + const { id } = await createRule(supertest, log, rule); + const hookAction = await createWebHookRuleAction(supertest); + await createLegacyRuleAction(supertest, id, hookAction.id); + + await retry.try(async () => { + const stats = await getStats(supertest, log); + const expected: RulesTypeUsage = { + ...getInitialDetectionMetrics().detection_rules.detection_rule_usage, + threat_match: { + ...getInitialDetectionMetrics().detection_rules.detection_rule_usage.threat_match, + disabled: 1, + legacy_notifications_disabled: 1, + }, + custom_total: { + ...getInitialDetectionMetrics().detection_rules.detection_rule_usage.custom_total, + disabled: 1, + legacy_notifications_disabled: 1, + }, + }; + expect(stats.detection_rules.detection_rule_usage).to.eql(expected); + }); + }); + + it('should show "legacy_notifications_enabled" to be "1" for rule that has at least "1" legacy action(s) and the alert is "enabled"/"active"', async () => { + const rule: ThreatMatchRuleCreateProps = { + ...getSimpleThreatMatch('rule-1', true), + index: ['telemetry'], + threat_index: ['telemetry'], + threat_mapping: [ + { + entries: [ + { + field: 'keyword', + value: 'keyword', + type: 'mapping', + }, + ], + }, + ], + }; + const { id } = await createRule(supertest, log, rule); + const hookAction = await createWebHookRuleAction(supertest); + await createLegacyRuleAction(supertest, id, hookAction.id); + await waitForRuleSuccess({ supertest, log, id }); + await waitForAlertsToBePresent(supertest, log, 4, [id]); + + await retry.try(async () => { + const stats = await getStats(supertest, log); + const expected: RulesTypeUsage = { + ...getInitialDetectionMetrics().detection_rules.detection_rule_usage, + threat_match: { + ...getInitialDetectionMetrics().detection_rules.detection_rule_usage.threat_match, + alerts: 4, + enabled: 1, + legacy_notifications_enabled: 1, + }, + custom_total: { + ...getInitialDetectionMetrics().detection_rules.detection_rule_usage.custom_total, + alerts: 4, + enabled: 1, + legacy_notifications_enabled: 1, + }, + }; + expect(stats.detection_rules.detection_rule_usage).to.eql(expected); + }); + }); + }); + + describe('"pre-packaged"/"immutable" rules', async () => { + it('should show "legacy_notifications_disabled" to be "1", "has_notification" to be "false, "has_legacy_notification" to be "true" for rule that has at least "1" action(s) and the alert is "disabled"/"in-active"', async () => { + await installMockPrebuiltRules(supertest, es); + const immutableRule = await fetchRule(supertest, { ruleId: ELASTIC_SECURITY_RULE_ID }); + const hookAction = await createWebHookRuleAction(supertest); + const newRuleToUpdate = getSimpleRule(immutableRule.rule_id, false); + await updateRule(supertest, newRuleToUpdate); + await createLegacyRuleAction(supertest, immutableRule.id, hookAction.id); + + await retry.try(async () => { + const stats = await getStats(supertest, log); + // We have to search by "rule_name" since the "rule_id" it is storing is the Saved Object ID and not the rule_id + const foundRule = stats.detection_rules.detection_rule_detail.find( + (rule) => rule.rule_id === ELASTIC_SECURITY_RULE_ID + ); + if (foundRule == null) { + throw new Error('Found rule should not be null. Please change this end to end test.'); + } + const { + created_on: createdOn, + updated_on: updatedOn, + rule_id: ruleId, + rule_version: ruleVersion, + ...omittedFields + } = foundRule; + expect(omittedFields).to.eql({ + rule_name: 'Simple Rule Query', + rule_type: 'query', + enabled: false, + elastic_rule: true, + alert_count_daily: 0, + cases_count_total: 0, + has_notification: false, + has_legacy_notification: true, + has_legacy_investigation_field: false, + }); + expect( + stats.detection_rules.detection_rule_usage.elastic_total.notifications_disabled + ).to.eql(0); + expect( + stats.detection_rules.detection_rule_usage.elastic_total.legacy_notifications_enabled + ).to.eql(0); + expect( + stats.detection_rules.detection_rule_usage.elastic_total.legacy_notifications_disabled + ).to.eql(1); + expect( + stats.detection_rules.detection_rule_usage.elastic_total.notifications_enabled + ).to.eql(0); + expect(stats.detection_rules.detection_rule_usage.custom_total).to.eql( + getInitialDetectionMetrics().detection_rules.detection_rule_usage.custom_total + ); + }); + }); + + it('should show "legacy_notifications_enabled" to be "1", "has_notification" to be "false, "has_legacy_notification" to be "true" for rule that has at least "1" action(s) and the alert is "enabled"/"active"', async () => { + await installMockPrebuiltRules(supertest, es); + const immutableRule = await fetchRule(supertest, { ruleId: ELASTIC_SECURITY_RULE_ID }); + const hookAction = await createWebHookRuleAction(supertest); + const newRuleToUpdate = getSimpleRule(immutableRule.rule_id, true); + await updateRule(supertest, newRuleToUpdate); + await createLegacyRuleAction(supertest, immutableRule.id, hookAction.id); + + await retry.try(async () => { + const stats = await getStats(supertest, log); + // We have to search by "rule_name" since the "rule_id" it is storing is the Saved Object ID and not the rule_id + const foundRule = stats.detection_rules.detection_rule_detail.find( + (rule) => rule.rule_id === ELASTIC_SECURITY_RULE_ID + ); + if (foundRule == null) { + throw new Error('Found rule should not be null. Please change this end to end test.'); + } + const { + created_on: createdOn, + updated_on: updatedOn, + rule_id: ruleId, + rule_version: ruleVersion, + ...omittedFields + } = foundRule; + expect(omittedFields).to.eql({ + rule_name: 'Simple Rule Query', + rule_type: 'query', + enabled: true, + elastic_rule: true, + alert_count_daily: 0, + cases_count_total: 0, + has_notification: false, + has_legacy_notification: true, + has_legacy_investigation_field: false, + }); + expect( + stats.detection_rules.detection_rule_usage.elastic_total.notifications_disabled + ).to.eql(0); + expect( + stats.detection_rules.detection_rule_usage.elastic_total.legacy_notifications_enabled + ).to.eql(1); + expect( + stats.detection_rules.detection_rule_usage.elastic_total.legacy_notifications_disabled + ).to.eql(0); + expect( + stats.detection_rules.detection_rule_usage.elastic_total.notifications_enabled + ).to.eql(0); + expect(stats.detection_rules.detection_rule_usage.custom_total).to.eql( + getInitialDetectionMetrics().detection_rules.detection_rule_usage.custom_total + ); + }); + }); + }); + }); +}; diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/group5/config.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/user_roles/configs/ess.config.ts similarity index 63% rename from x-pack/test/detection_engine_api_integration/security_and_spaces/group5/config.ts rename to x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/user_roles/configs/ess.config.ts index 2430b8f2148d9..59e01e74c719c 100644 --- a/x-pack/test/detection_engine_api_integration/security_and_spaces/group5/config.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/user_roles/configs/ess.config.ts @@ -7,12 +7,16 @@ import { FtrConfigProviderContext } from '@kbn/test'; -// eslint-disable-next-line import/no-default-export export default async function ({ readConfigFile }: FtrConfigProviderContext) { - const functionalConfig = await readConfigFile(require.resolve('../config.base.ts')); + const functionalConfig = await readConfigFile( + require.resolve('../../../../../config/ess/config.base.trial') + ); return { ...functionalConfig.getAll(), - testFiles: [require.resolve('.')], + testFiles: [require.resolve('..')], + junit: { + reportName: 'Detection Engine ESS - User roles API Integration Tests', + }, }; } diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/user_roles/configs/serverless.config.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/user_roles/configs/serverless.config.ts new file mode 100644 index 0000000000000..d8e9843c3eb92 --- /dev/null +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/user_roles/configs/serverless.config.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 { createTestConfig } from '../../../../../config/serverless/config.base'; + +export default createTestConfig({ + testFiles: [require.resolve('..')], + junit: { + reportName: 'Detection Engine Serverless - User roles API Integration Tests', + }, +}); diff --git a/x-pack/plugins/reporting/server/services.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/user_roles/index.ts similarity index 50% rename from x-pack/plugins/reporting/server/services.ts rename to x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/user_roles/index.ts index a09442ec32793..7c1d0fe7cc751 100644 --- a/x-pack/plugins/reporting/server/services.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/user_roles/index.ts @@ -4,9 +4,10 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ +import { FtrProviderContext } from '../../../../ftr_provider_context'; -import { FieldFormatsStart } from '@kbn/field-formats-plugin/server'; -import { createGetterSetter } from '@kbn/kibana-utils-plugin/server'; - -export const [getFieldFormats, setFieldFormats] = - createGetterSetter('FieldFormats'); +export default ({ loadTestFile }: FtrProviderContext): void => { + describe('Detection User Roles APIs', function () { + loadTestFile(require.resolve('./read_privileges')); + }); +}; diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/group10/read_privileges.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/user_roles/read_privileges.ts similarity index 98% rename from x-pack/test/detection_engine_api_integration/security_and_spaces/group10/read_privileges.ts rename to x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/user_roles/read_privileges.ts index b95c6771367f4..ee55d4ebfb331 100644 --- a/x-pack/test/detection_engine_api_integration/security_and_spaces/group10/read_privileges.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/user_roles/read_privileges.ts @@ -9,15 +9,17 @@ import expect from '@kbn/expect'; import { DETECTION_ENGINE_PRIVILEGES_URL } from '@kbn/security-solution-plugin/common/constants'; import { ROLES } from '@kbn/security-solution-plugin/common/test'; -import { FtrProviderContext } from '../../common/ftr_provider_context'; -import { createUserAndRole, deleteUserAndRole } from '../../../common/services/security_solution'; +import { + createUserAndRole, + deleteUserAndRole, +} from '../../../../../common/services/security_solution'; +import { FtrProviderContext } from '../../../../ftr_provider_context'; -// eslint-disable-next-line import/no-default-export export default ({ getService }: FtrProviderContext) => { const supertest = getService('supertest'); const supertestWithoutAuth = getService('supertestWithoutAuth'); - describe('read_privileges', () => { + describe('@ess @serverless @brokenInServerless 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({ diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/actions/create_new_action.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/actions/create_new_webhook_action.ts similarity index 87% rename from x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/actions/create_new_action.ts rename to x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/actions/create_new_webhook_action.ts index 1ddce1f07114c..79ea9738372f0 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/actions/create_new_action.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/actions/create_new_webhook_action.ts @@ -5,6 +5,7 @@ * 2.0. */ +import { X_ELASTIC_INTERNAL_ORIGIN_REQUEST } from '@kbn/core-http-common'; import { RuleAction } from '@kbn/security-solution-plugin/common/api/detection_engine'; import type SuperTest from 'supertest'; @@ -23,7 +24,7 @@ export const createWebHookRuleAction = async ( await supertest .post('/api/actions/action') .set('kbn-xsrf', 'true') - .set('x-elastic-internal-origin', 'foo') + .set(X_ELASTIC_INTERNAL_ORIGIN_REQUEST, 'foo') .send(getWebHookAction()) .expect(200) ).body; diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/actions/index.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/actions/index.ts index f91323f94de59..9accb2b089280 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/actions/index.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/actions/index.ts @@ -6,5 +6,5 @@ */ export * from './get_slack_action'; export * from './get_web_hook_action'; -export * from './create_new_action'; +export * from './create_new_webhook_action'; export * from './legacy_actions'; diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/alerts/get_preview_alerts.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/alerts/get_preview_alerts.ts new file mode 100644 index 0000000000000..744027c3fd4eb --- /dev/null +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/alerts/get_preview_alerts.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 type { Client } from '@elastic/elasticsearch'; +import { ALERT_RULE_UUID } from '@kbn/rule-data-utils'; +import { DetectionAlert } from '@kbn/security-solution-plugin/common/api/detection_engine'; +import { RiskEnrichmentFields } from '@kbn/security-solution-plugin/server/lib/detection_engine/rule_types/utils/enrichments/types'; +import { refreshIndex } from '../refresh_index'; + +/** + * Refresh an index, making changes available to search. + * Useful for tests where we want to ensure that a rule does NOT create alerts, e.g. testing exceptions. + * @param es The ElasticSearch handle + */ +export const getPreviewAlerts = async ({ + es, + previewId, + size, + sort, +}: { + es: Client; + previewId: string; + size?: number; + sort?: string[]; +}) => { + const index = '.preview.alerts-security.alerts-*'; + await refreshIndex(es, index); + const query = { + bool: { + filter: { + term: { + [ALERT_RULE_UUID]: previewId, + }, + }, + }, + }; + const result = await es.search({ + index, + size, + query, + sort, + }); + return result.hits.hits; +}; diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/alerts/index.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/alerts/index.ts index ce29837b34f6e..975c6ffa509cc 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/alerts/index.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/alerts/index.ts @@ -14,9 +14,10 @@ export * from './get_open_alerts'; export * from './get_alerts_by_ids'; export * from './get_query_alerts_ids'; export * from './get_alerts_by_id'; -export * from './remove_random_valued_properties'; +export * from './remove_random_valued_properties_from_alert'; export * from './set_alert_status'; export * from './get_alert_status_empty_response'; export * from './get_query_alert_ids'; export * from './set_alert_tags'; +export * from './get_preview_alerts'; export * from './migrations'; diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/alerts/remove_random_valued_properties.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/alerts/remove_random_valued_properties.ts deleted file mode 100644 index 8530c085e1a5d..0000000000000 --- a/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/alerts/remove_random_valued_properties.ts +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { DetectionAlert } from '@kbn/security-solution-plugin/common/api/detection_engine'; -import { ALERT_LAST_DETECTED, ALERT_START } from '@kbn/rule-data-utils'; - -export const removeRandomValuedProperties = (alert: DetectionAlert | undefined) => { - if (!alert) { - return undefined; - } - const { - 'kibana.version': version, - 'kibana.alert.rule.execution.uuid': execUuid, - 'kibana.alert.rule.uuid': uuid, - '@timestamp': timestamp, - 'kibana.alert.rule.created_at': createdAt, - 'kibana.alert.rule.updated_at': updatedAt, - 'kibana.alert.uuid': alertUuid, - [ALERT_START]: alertStart, - [ALERT_LAST_DETECTED]: lastDetected, - ...restOfAlert - } = alert; - return restOfAlert; -}; diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/rule_execution_logic/utils.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/alerts/remove_random_valued_properties_from_alert.ts similarity index 87% rename from x-pack/test/detection_engine_api_integration/security_and_spaces/rule_execution_logic/utils.ts rename to x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/alerts/remove_random_valued_properties_from_alert.ts index 8530c085e1a5d..3161fe1a61a6e 100644 --- a/x-pack/test/detection_engine_api_integration/security_and_spaces/rule_execution_logic/utils.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/alerts/remove_random_valued_properties_from_alert.ts @@ -8,7 +8,7 @@ import { DetectionAlert } from '@kbn/security-solution-plugin/common/api/detection_engine'; import { ALERT_LAST_DETECTED, ALERT_START } from '@kbn/rule-data-utils'; -export const removeRandomValuedProperties = (alert: DetectionAlert | undefined) => { +export const removeRandomValuedPropertiesFromAlert = (alert: DetectionAlert | undefined) => { if (!alert) { return undefined; } @@ -20,6 +20,7 @@ export const removeRandomValuedProperties = (alert: DetectionAlert | undefined) 'kibana.alert.rule.created_at': createdAt, 'kibana.alert.rule.updated_at': updatedAt, 'kibana.alert.uuid': alertUuid, + 'kibana.alert.url': alertURL, [ALERT_START]: alertStart, [ALERT_LAST_DETECTED]: lastDetected, ...restOfAlert diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/event_log/delete_all_event_log_execution_events.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/event_log/delete_all_event_log_execution_events.ts new file mode 100644 index 0000000000000..998033d185486 --- /dev/null +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/event_log/delete_all_event_log_execution_events.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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type { ToolingLog } from '@kbn/tooling-log'; +import type { Client } from '@elastic/elasticsearch'; + +import { countDownES } from '../count_down_es'; + +/** + * Remove all .kibana-event-log-* documents with an execution.uuid + * This will retry 50 times before giving up and hopefully still not interfere with other tests + * @param es The ElasticSearch handle + * @param log The tooling logger + */ +export const deleteAllEventLogExecutionEvents = async ( + es: Client, + log: ToolingLog +): Promise => { + return countDownES( + async () => { + return es.deleteByQuery( + { + index: '.kibana-event-log-*', + q: '_exists_:kibana.alert.rule.execution.uuid', + wait_for_completion: true, + refresh: true, + body: {}, + }, + { meta: true } + ); + }, + 'deleteAllEventLogExecutionEvents', + log + ); +}; diff --git a/x-pack/plugins/reporting/server/export_types/printable_pdf_v2/index.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/event_log/index.ts similarity index 81% rename from x-pack/plugins/reporting/server/export_types/printable_pdf_v2/index.ts rename to x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/event_log/index.ts index f27635ae6fc49..c10ed51052bc3 100644 --- a/x-pack/plugins/reporting/server/export_types/printable_pdf_v2/index.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/event_log/index.ts @@ -4,5 +4,4 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ - -export { PdfExportType } from './printable_pdf_v2'; +export * from './delete_all_event_log_execution_events'; diff --git a/x-pack/test/detection_engine_api_integration/utils/get_detection_metrics_from_body.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/get_detection_metrics_from_body.ts similarity index 59% rename from x-pack/test/detection_engine_api_integration/utils/get_detection_metrics_from_body.ts rename to x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/get_detection_metrics_from_body.ts index 92e17ba61fe03..20febd5e9180f 100644 --- a/x-pack/test/detection_engine_api_integration/utils/get_detection_metrics_from_body.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/get_detection_metrics_from_body.ts @@ -6,7 +6,6 @@ */ import type { DetectionMetrics } from '@kbn/security-solution-plugin/server/usage/detections/types'; -import type { RiskEngineMetrics } from '@kbn/security-solution-plugin/server/usage/risk_engine/types'; /** * Given a body this will return the detection metrics from it. @@ -24,20 +23,3 @@ export const getDetectionMetricsFromBody = ( ): DetectionMetrics => { return body[0].stats.stack_stats.kibana.plugins.security_solution.detectionMetrics; }; - -/** - * Given a body this will return the risk engine metrics from it. - * @param body The Stats body - * @returns Detection metrics - */ -export const getRiskEngineMetricsFromBody = ( - body: Array<{ - stats: { - stack_stats: { - kibana: { plugins: { security_solution: { riskEngineMetrics: {} } } }; - }; - }; - }> -): RiskEngineMetrics => { - return body[0].stats.stack_stats.kibana.plugins.security_solution.riskEngineMetrics; -}; diff --git a/x-pack/test/detection_engine_api_integration/utils/get_stats.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/get_stats.ts similarity index 57% rename from x-pack/test/detection_engine_api_integration/utils/get_stats.ts rename to x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/get_stats.ts index d042bdc4d53f7..9415f6900a54f 100644 --- a/x-pack/test/detection_engine_api_integration/utils/get_stats.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/get_stats.ts @@ -8,17 +8,13 @@ import type { ToolingLog } from '@kbn/tooling-log'; import type SuperTest from 'supertest'; import type { DetectionMetrics } from '@kbn/security-solution-plugin/server/usage/detections/types'; -import type { RiskEngineMetrics } from '@kbn/security-solution-plugin/server/usage/risk_engine/types'; import { ELASTIC_HTTP_VERSION_HEADER, X_ELASTIC_INTERNAL_ORIGIN_REQUEST, } from '@kbn/core-http-common'; import { getStatsUrl } from './get_stats_url'; -import { - getDetectionMetricsFromBody, - getRiskEngineMetricsFromBody, -} from './get_detection_metrics_from_body'; +import { getDetectionMetricsFromBody } from './get_detection_metrics_from_body'; /** * Gets the stats from the stats endpoint. @@ -45,29 +41,3 @@ export const getStats = async ( return getDetectionMetricsFromBody(response.body); }; - -/** - * Gets the stats from the stats endpoint. - * @param supertest The supertest agent. - * @returns The detection metrics - */ -export const getRiskEngineStats = async ( - supertest: SuperTest.SuperTest, - log: ToolingLog -): Promise => { - const response = await supertest - .post(getStatsUrl()) - .set('kbn-xsrf', 'true') - .set(ELASTIC_HTTP_VERSION_HEADER, '2') - .set(X_ELASTIC_INTERNAL_ORIGIN_REQUEST, 'kibana') - .send({ unencrypted: true, refreshCache: true }); - if (response.status !== 200) { - log.error( - `Did not get an expected 200 "ok" when getting the stats for risk engine. CI issues could happen. Suspect this line if you are seeing CI issues. body: ${JSON.stringify( - response.body - )}, status: ${JSON.stringify(response.status)}` - ); - } - - return getRiskEngineMetricsFromBody(response.body); -}; diff --git a/x-pack/test/detection_engine_api_integration/utils/get_stats_url.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/get_stats_url.ts similarity index 100% rename from x-pack/test/detection_engine_api_integration/utils/get_stats_url.ts rename to x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/get_stats_url.ts diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/index.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/index.ts index 9af5821d08ac3..0b7c66f57cb2a 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/index.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/index.ts @@ -9,12 +9,11 @@ export * from './exception_list_and_item'; export * from './alerts'; export * from './actions'; export * from './data_generator'; +export * from './telemetry'; +export * from './event_log'; +export * from './machine_learning'; -export * from './rules/get_rule_so_by_id'; -export * from './rules/create_rule_saved_object'; -export * from './rules/get_rule_with_legacy_investigation_fields'; export * from './get_index_name_from_load'; - export * from './count_down_test'; export * from './count_down_es'; export * from './update_username'; @@ -22,3 +21,6 @@ export * from './refresh_index'; export * from './wait_for'; export * from './route_with_namespace'; export * from './wait_for_index_to_populate'; +export * from './get_stats'; +export * from './get_detection_metrics_from_body'; +export * from './get_stats_url'; diff --git a/x-pack/plugins/reporting/server/export_types/png_v2/index.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/machine_learning/index.ts similarity index 85% rename from x-pack/plugins/reporting/server/export_types/png_v2/index.ts rename to x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/machine_learning/index.ts index 301395447f3c8..6d6870b7ac92a 100644 --- a/x-pack/plugins/reporting/server/export_types/png_v2/index.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/machine_learning/index.ts @@ -4,5 +4,4 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ - -export { PngExportType } from './png_v2'; +export * from './machine_learning_setup'; diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/machine_learning/machine_learning_setup.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/machine_learning/machine_learning_setup.ts new file mode 100644 index 0000000000000..d7c7e6387c739 --- /dev/null +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/machine_learning/machine_learning_setup.ts @@ -0,0 +1,55 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type SuperTest from 'supertest'; +import { getCommonRequestHeader } from '../../../../../functional/services/ml/common_api'; + +export const executeSetupModuleRequest = async ({ + module, + rspCode, + supertest, +}: { + module: string; + rspCode: number; + supertest: SuperTest.SuperTest; +}) => { + const { body } = await supertest + .post(`/internal/ml/modules/setup/${module}`) + .set(getCommonRequestHeader('1')) + .send({ + prefix: '', + groups: ['auditbeat'], + indexPatternName: 'auditbeat-*', + startDatafeed: false, + useDedicatedIndex: true, + applyToAllSpaces: true, + }) + .expect(rspCode); + + return body; +}; + +export const forceStartDatafeeds = async ({ + jobId, + rspCode, + supertest, +}: { + jobId: string; + rspCode: number; + supertest: SuperTest.SuperTest; +}) => { + const { body } = await supertest + .post(`/internal/ml/jobs/force_start_datafeeds`) + .set(getCommonRequestHeader('1')) + .send({ + datafeedIds: [`datafeed-${jobId}`], + start: new Date().getUTCMilliseconds(), + }) + .expect(rspCode); + + return body; +}; diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/create_legacy_rule_action.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/create_legacy_rule_action.ts new file mode 100644 index 0000000000000..8e0cb59d5ee90 --- /dev/null +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/create_legacy_rule_action.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 SuperTest from 'supertest'; + +import { UPDATE_OR_CREATE_LEGACY_ACTIONS } from '@kbn/security-solution-plugin/common/constants'; + +export const createLegacyRuleAction = async ( + supertest: SuperTest.SuperTest, + alertId: string, + connectorId: string +): Promise => + supertest + .post(UPDATE_OR_CREATE_LEGACY_ACTIONS) + .set('kbn-xsrf', 'true') + .set('elastic-api-version', '1') + .query({ alert_id: alertId }) + .send({ + name: 'Legacy notification with one action', + interval: '1h', + actions: [ + { + id: connectorId, + group: 'default', + params: { + message: 'Hourly\nRule {{context.rule.name}} generated {{state.signals_count}} alerts', + }, + actionTypeId: '.slack', + }, + ], + }); diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/create_rule.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/create_rule.ts index cd3fb09ced4e9..ac6e44b2aab83 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/create_rule.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/create_rule.ts @@ -5,6 +5,7 @@ * 2.0. */ +import { ELASTIC_HTTP_VERSION_HEADER } from '@kbn/core-http-common'; import type { ToolingLog } from '@kbn/tooling-log'; import type SuperTest from 'supertest'; import type { @@ -35,7 +36,7 @@ export const createRule = async ( const response = await supertest .post(route) .set('kbn-xsrf', 'true') - .set('elastic-api-version', '2023-10-31') + .set(ELASTIC_HTTP_VERSION_HEADER, '2023-10-31') .send(rule); if (response.status === 409) { if (rule.rule_id != null) { diff --git a/x-pack/test/detection_engine_api_integration/utils/create_rule_with_auth.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/create_rule_with_auth.ts similarity index 100% rename from x-pack/test/detection_engine_api_integration/utils/create_rule_with_auth.ts rename to x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/create_rule_with_auth.ts diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/get_rule_for_alert_testing.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/get_rule_for_alert_testing.ts index d6d51ebb52d00..5649031185feb 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/get_rule_for_alert_testing.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/get_rule_for_alert_testing.ts @@ -19,7 +19,7 @@ export const getRuleForAlertTesting = ( ruleId = 'rule-1', enabled = true ): QueryRuleCreateProps => ({ - name: 'Signal Testing Query', + name: 'Alert Testing Query', description: 'Tests a simple query', enabled, risk_score: 1, diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/get_rule_for_alert_testing_with_timestamp_override.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/get_rule_for_alert_testing_with_timestamp_override.ts new file mode 100644 index 0000000000000..86fc55bd29652 --- /dev/null +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/get_rule_for_alert_testing_with_timestamp_override.ts @@ -0,0 +1,27 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type { QueryRuleCreateProps } from '@kbn/security-solution-plugin/common/api/detection_engine'; + +export const getRuleForAlertTestingWithTimestampOverride = ( + index: string[], + ruleId = 'rule-1', + enabled = true, + timestampOverride = 'event.ingested' +): QueryRuleCreateProps => ({ + name: 'Alert Testing Query', + description: 'Tests a simple query', + enabled, + risk_score: 1, + rule_id: ruleId, + severity: 'high', + index, + type: 'query', + query: '*:*', + timestamp_override: timestampOverride, + from: '1900-01-01T00:00:00.000Z', +}); diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/get_simple_ml_rule.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/get_simple_ml_rule.ts new file mode 100644 index 0000000000000..a8fe28d54f24e --- /dev/null +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/get_simple_ml_rule.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 type { RuleCreateProps } from '@kbn/security-solution-plugin/common/api/detection_engine'; + +/** + * This is a representative ML rule payload as expected by the server + * @param ruleId The rule id + * @param enabled Set to tru to enable it, by default it is off + */ +export const getSimpleMlRule = (ruleId = 'rule-1', enabled = false): RuleCreateProps => ({ + name: 'Simple ML Rule', + description: 'Simple Machine Learning Rule', + enabled, + anomaly_threshold: 44, + risk_score: 1, + rule_id: ruleId, + severity: 'high', + machine_learning_job_id: ['some_job_id'], + type: 'machine_learning', +}); diff --git a/x-pack/test/detection_engine_api_integration/utils/get_simple_threat_match.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/get_simple_threat_match.ts similarity index 100% rename from x-pack/test/detection_engine_api_integration/utils/get_simple_threat_match.ts rename to x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/get_simple_threat_match.ts diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/index.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/index.ts index 3e22a15665fc2..db5ccb307395e 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/index.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/index.ts @@ -31,6 +31,13 @@ export * from './get_saved_query_rule_for_alert_testing'; export * from './get_rule_so_by_id'; export * from './create_rule_saved_object'; export * from './get_rule_with_legacy_investigation_fields'; +export * from './create_rule_with_auth'; +export * from './preview_rule'; +export * from './preview_rule_with_exception_entries'; +export * from './patch_rule'; export * from './generate_event'; +export * from './create_legacy_rule_action'; +export * from './get_simple_threat_match'; +export * from './get_simple_ml_rule'; export * from './prebuilt_rules'; diff --git a/x-pack/test/detection_engine_api_integration/utils/patch_rule.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/patch_rule.ts similarity index 100% rename from x-pack/test/detection_engine_api_integration/utils/patch_rule.ts rename to x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/patch_rule.ts diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/preview_rule.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/preview_rule.ts new file mode 100644 index 0000000000000..ec060c4076404 --- /dev/null +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/preview_rule.ts @@ -0,0 +1,51 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type SuperTest from 'supertest'; +import type { + RuleCreateProps, + PreviewRulesSchema, + RulePreviewLogs, +} from '@kbn/security-solution-plugin/common/api/detection_engine'; + +import { DETECTION_ENGINE_RULES_PREVIEW } from '@kbn/security-solution-plugin/common/constants'; + +/** + * Runs the preview for a rule. Any generated alerts will be written to .preview.alerts. + * This is much faster than actually running the rule, and can also quickly simulate multiple + * consecutive rule runs, e.g. for ensuring that rule state is properly handled across runs. + * @param supertest The supertest deps + * @param rule The rule to create + */ +export const previewRule = async ({ + supertest, + rule, + invocationCount = 1, + timeframeEnd = new Date(), +}: { + supertest: SuperTest.SuperTest; + rule: RuleCreateProps; + invocationCount?: number; + timeframeEnd?: Date; +}): Promise<{ + previewId: string; + logs: RulePreviewLogs[]; + isAborted: boolean; +}> => { + const previewRequest: PreviewRulesSchema = { + ...rule, + invocationCount, + timeframeEnd: timeframeEnd.toISOString(), + }; + const response = await supertest + .post(DETECTION_ENGINE_RULES_PREVIEW) + .set('kbn-xsrf', 'true') + .set('elastic-api-version', '2023-10-31') + .send(previewRequest) + .expect(200); + return response.body; +}; diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/preview_rule_with_exception_entries.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/preview_rule_with_exception_entries.ts new file mode 100644 index 0000000000000..fb5d480bbbffc --- /dev/null +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/preview_rule_with_exception_entries.ts @@ -0,0 +1,65 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type { ToolingLog } from '@kbn/tooling-log'; +import type SuperTest from 'supertest'; +import type { NonEmptyEntriesArray, OsTypeArray } from '@kbn/securitysolution-io-ts-list-types'; +import type { RuleCreateProps } from '@kbn/security-solution-plugin/common/api/detection_engine'; + +import { + createContainerWithEntries, + createContainerWithEndpointEntries, +} from '../exception_list_and_item'; +import { previewRule } from './preview_rule'; + +/** + * Convenience testing function where you can pass in just the entries and you will + * get a rule created with the entries added to an exception list and exception list item + * all auto-created at once. + * @param supertest super test agent + * @param rule The rule to create and attach an exception list to + * @param entries The entries to create the rule and exception list from + * @param endpointEntries The endpoint entries to create the rule and exception list from + * @param osTypes The os types to optionally add or not to add to the container + */ +export const previewRuleWithExceptionEntries = async ({ + supertest, + log, + rule, + entries, + endpointEntries, + invocationCount, + timeframeEnd, +}: { + supertest: SuperTest.SuperTest; + log: ToolingLog; + rule: RuleCreateProps; + entries: NonEmptyEntriesArray[]; + endpointEntries?: Array<{ + entries: NonEmptyEntriesArray; + osTypes: OsTypeArray | undefined; + }>; + invocationCount?: number; + timeframeEnd?: Date; +}) => { + const maybeExceptionList = await createContainerWithEntries(supertest, log, entries); + const maybeEndpointList = await createContainerWithEndpointEntries( + supertest, + log, + endpointEntries ?? [] + ); + + return previewRule({ + supertest, + rule: { + ...rule, + exceptions_list: [...maybeExceptionList, ...maybeEndpointList], + }, + invocationCount, + timeframeEnd, + }); +}; diff --git a/x-pack/test/detection_engine_api_integration/utils/get_security_telemetry_stats.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/telemetry/get_security_telemetry_stats.ts similarity index 86% rename from x-pack/test/detection_engine_api_integration/utils/get_security_telemetry_stats.ts rename to x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/telemetry/get_security_telemetry_stats.ts index 7eb00b7ff3138..462cdecbb498d 100644 --- a/x-pack/test/detection_engine_api_integration/utils/get_security_telemetry_stats.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/telemetry/get_security_telemetry_stats.ts @@ -9,6 +9,10 @@ import type { ToolingLog } from '@kbn/tooling-log'; import type SuperTest from 'supertest'; import { SECURITY_TELEMETRY_URL } from '@kbn/security-solution-plugin/common/constants'; +import { + ELASTIC_HTTP_VERSION_HEADER, + X_ELASTIC_INTERNAL_ORIGIN_REQUEST, +} from '@kbn/core-http-common'; /** * Gets the stats from the stats endpoint within specifically the security_solutions application. @@ -23,7 +27,8 @@ export const getSecurityTelemetryStats = async ( const response = await supertest .get(SECURITY_TELEMETRY_URL) .set('kbn-xsrf', 'true') - .set('elastic-api-version', '1') + .set(ELASTIC_HTTP_VERSION_HEADER, '1') + .set(X_ELASTIC_INTERNAL_ORIGIN_REQUEST, 'kibana') .send({ unencrypted: true, refreshCache: true }); if (response.status !== 200) { log.error( diff --git a/x-pack/plugins/reporting/server/export_types/csv_searchsource_immediate/index.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/telemetry/index.ts similarity index 70% rename from x-pack/plugins/reporting/server/export_types/csv_searchsource_immediate/index.ts rename to x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/telemetry/index.ts index e17fa75f8e7f9..c784edd7f618b 100644 --- a/x-pack/plugins/reporting/server/export_types/csv_searchsource_immediate/index.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/telemetry/index.ts @@ -4,5 +4,5 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ - -export { CsvSearchSourceImmediateExportType } from './csv_searchsource_immediate'; +export * from './get_security_telemetry_stats'; +export * from './remove_time_fields_from_telemetry_stats'; diff --git a/x-pack/test/detection_engine_api_integration/utils/remove_time_fields_from_telemetry_stats.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/telemetry/remove_time_fields_from_telemetry_stats.ts similarity index 100% rename from x-pack/test/detection_engine_api_integration/utils/remove_time_fields_from_telemetry_stats.ts rename to x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/telemetry/remove_time_fields_from_telemetry_stats.ts diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/wait_for_index_to_populate.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/wait_for_index_to_populate.ts index 74e3e8a253769..ceba42efd1793 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/wait_for_index_to_populate.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/wait_for_index_to_populate.ts @@ -7,7 +7,7 @@ import type { ToolingLog } from '@kbn/tooling-log'; import type { Client } from '@elastic/elasticsearch'; -import { waitFor } from '../../../../detection_engine_api_integration/utils/wait_for'; +import { waitFor } from './wait_for'; /** * Waits for the given index to contain documents diff --git a/x-pack/test/security_solution_api_integration/test_suites/entity_analytics/utils/get_risk_engine_metrics_from_body.ts b/x-pack/test/security_solution_api_integration/test_suites/entity_analytics/utils/get_risk_engine_metrics_from_body.ts new file mode 100644 index 0000000000000..c8ec19e448402 --- /dev/null +++ b/x-pack/test/security_solution_api_integration/test_suites/entity_analytics/utils/get_risk_engine_metrics_from_body.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 { RiskEngineMetrics } from '@kbn/security-solution-plugin/server/usage/risk_engine/types'; + +/** + * Given a body this will return the risk engine metrics from it. + * @param body The Stats body + * @returns Detection metrics + */ +export const getRiskEngineMetricsFromBody = ( + body: Array<{ + stats: { + stack_stats: { + kibana: { plugins: { security_solution: { riskEngineMetrics: {} } } }; + }; + }; + }> +): RiskEngineMetrics => { + return body[0].stats.stack_stats.kibana.plugins.security_solution.riskEngineMetrics; +}; diff --git a/x-pack/test/security_solution_api_integration/test_suites/entity_analytics/utils/get_risk_engine_stats.ts b/x-pack/test/security_solution_api_integration/test_suites/entity_analytics/utils/get_risk_engine_stats.ts index c5343372ce99a..5629e0da9a89d 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/entity_analytics/utils/get_risk_engine_stats.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/entity_analytics/utils/get_risk_engine_stats.ts @@ -7,44 +7,14 @@ import type { ToolingLog } from '@kbn/tooling-log'; import type SuperTest from 'supertest'; -import type { DetectionMetrics } from '@kbn/security-solution-plugin/server/usage/detections/types'; import type { RiskEngineMetrics } from '@kbn/security-solution-plugin/server/usage/risk_engine/types'; import { ELASTIC_HTTP_VERSION_HEADER, X_ELASTIC_INTERNAL_ORIGIN_REQUEST, } from '@kbn/core-http-common'; -import { getStatsUrl } from '../../../../detection_engine_api_integration/utils/get_stats_url'; -import { - getDetectionMetricsFromBody, - getRiskEngineMetricsFromBody, -} from '../../../../detection_engine_api_integration/utils/get_detection_metrics_from_body'; - -/** - * Gets the stats from the stats endpoint. - * @param supertest The supertest agent. - * @returns The detection metrics - */ -export const getStats = async ( - supertest: SuperTest.SuperTest, - log: ToolingLog -): Promise => { - const response = await supertest - .post(getStatsUrl()) - .set('kbn-xsrf', 'true') - .set(ELASTIC_HTTP_VERSION_HEADER, '2') - .set(X_ELASTIC_INTERNAL_ORIGIN_REQUEST, 'kibana') - .send({ unencrypted: true, refreshCache: true }); - if (response.status !== 200) { - log.error( - `Did not get an expected 200 "ok" when getting the stats for detections. CI issues could happen. Suspect this line if you are seeing CI issues. body: ${JSON.stringify( - response.body - )}, status: ${JSON.stringify(response.status)}` - ); - } - - return getDetectionMetricsFromBody(response.body); -}; +import { getStatsUrl } from '../../detections_response/utils/get_stats_url'; +import { getRiskEngineMetricsFromBody } from './get_risk_engine_metrics_from_body'; /** * Gets the stats from the stats endpoint. diff --git a/x-pack/test/security_solution_api_integration/tsconfig.json b/x-pack/test/security_solution_api_integration/tsconfig.json index 4dfd3ef6ba30d..782bc4fd46b32 100644 --- a/x-pack/test/security_solution_api_integration/tsconfig.json +++ b/x-pack/test/security_solution_api_integration/tsconfig.json @@ -30,6 +30,8 @@ "@kbn/core-saved-objects-server", "@kbn/core", "@kbn/alerting-plugin", + "@kbn/securitysolution-ecs", + "@kbn/securitysolution-rules", "@kbn/core-http-common", "@kbn/securitysolution-ecs", "@kbn/fleet-plugin", diff --git a/x-pack/test/security_solution_cypress/cypress/README.md b/x-pack/test/security_solution_cypress/cypress/README.md index c85ba1bea305f..8940d6c86e73e 100644 --- a/x-pack/test/security_solution_cypress/cypress/README.md +++ b/x-pack/test/security_solution_cypress/cypress/README.md @@ -42,11 +42,10 @@ Please, before opening a PR with the new test, please make sure that the test fa Note that we use tags in order to select which tests we want to execute: -- `@serverless` includes a test in the Serverless test suite for PRs (the so-called first quality gate). You need to explicitly add this tag to any test you want to run in CI for open PRs. These tests will run against a local, "simulated" serverless environment. -- `@serverlessQA` includes a test in the Serverless test suite for QA (the so-called second quality gate). You need to explicitly add this tag to any test you want to run in the CD pipeline against real serverless projects deployed in the Serverless QA environment. - - **NOTE:** We are adding this tag temporarily until we check the behavior of our tests in the second quality gate. +- `@serverless` includes a test in the Serverless test suite for PRs (the so-called first quality gate) and QA environemnt (the so-called second quality gate). You need to explicitly add this tag to any test you want to run in CI for serverless. - `@ess` includes a test in the normal, non-Serverless test suite. You need to explicitly add this tag to any test you want to run against a non-Serverless environment. - `@brokenInServerless` excludes a test from the Serverless test suite (even if it's tagged as `@serverless`). Indicates that a test should run in Serverless, but currently is broken. +- `@brokenInServerlessQA` excludes a test form the Serverless QA enviornment (second quality gate). Indicates that a test should run on it, but currently is broken. - `@skipInServerless` excludes a test from the Serverless test suite (even if it's tagged as `@serverless`). Could indicate many things, e.g. "the test is flaky in Serverless", "the test is Flaky in any type of environemnt", "the test has been temporarily excluded, see the comment above why". Please, before opening a PR with a new test, make sure that the test fails. If you never see your test fail you don’t know if your test is actually testing the right thing, or testing anything at all. @@ -72,6 +71,10 @@ Run the tests with the following yarn scripts from `x-pack/test/security_solutio | cypress:explore:run:ess | Runs all tests tagged as ESS in the `e2e/explore` directory in headless mode | | cypress:investigations:run:serverless | Runs all tests tagged as SERVERLESS in the `e2e/investigations` directory in headless mode | | cypress:explore:run:serverless | Runs all tests tagged as SERVERLESS in the `e2e/explore` directory in headless mode | +| cypress:open:qa:serverless | Opens the Cypress UI with all tests in the `e2e` directory tagged as SERVERLESS. This also creates an MKI project in console.qa enviornment. The kibana instance will reload when you make code changes. This is the recommended way to debug tests in QA. Follow the readme in order to learn about the known limitations. | +| cypress:run:qa:serverless | Runs all tests tagged as SERVERLESS placed in the `e2e` directory excluding `investigations` and `explore` directories in headless mode using the QA environment and real MKI projects.| +| cypress:run:qa:serverless:explore | Runs all tests tagged as SERVERLESS in the `e2e/explore` directory in headless mode using the QA environment and real MKI prorjects. | +| cypress:run:qa:serverless:investigations | Runs all tests tagged as SERVERLESS in the `e2e/investigations` directory in headless mode using the QA environment and reak MKI projects. | | junit:merge | Merges individual test reports into a single report and moves the report to the `junit` directory | Please note that all the headless mode commands do not open the Cypress UI and are typically used in CI/CD environments. The scripts that open the Cypress UI are useful for development and debugging. @@ -190,7 +193,7 @@ Task [cypress/support/es_archiver.ts](https://github.com/elastic/kibana/blob/mai Note that we use tags in order to select which tests we want to execute, if you want a test to be executed on serverless you need to add @serverless tag to it. -### Running the serverless tests locally +### Running serverless tests locally pointing to FTR serverless (First Quality Gate) Run the tests with the following yarn scripts from `x-pack/test/security_solution_cypress`: @@ -203,7 +206,7 @@ Run the tests with the following yarn scripts from `x-pack/test/security_solutio Please note that all the headless mode commands do not open the Cypress UI and are typically used in CI/CD environments. The scripts that open the Cypress UI are useful for development and debugging. -### PLIs +#### PLIs When running serverless Cypress tests, the following PLIs are set by default: ``` @@ -234,6 +237,97 @@ Per the way we set the environment during the execution process on CI, the above For test developing or test debugging purposes, you need to modify the configuration but without committing and pushing the changes in `x-pack/test/security_solution_cypress/serverless_config.ts`. + +### Running serverless tests locally pointing to a MKI project created in QA environment (Second Quality Gate) + +Run the tests with the following yarn scripts from `x-pack/test/security_solution_cypress`: + +| Script Name | Description | +| ----------- | ----------- | +| cypress:open:qa:serverless | Opens the Cypress UI with all tests in the `e2e` directory tagged as SERVERLESS. This also creates an MKI project in console.qa enviornment. The kibana instance will reload when you make code changes. This is the recommended way to debug tests in QA. Follow the readme in order to learn about the known limitations. | +| cypress:run:qa:serverless | Runs all tests tagged as SERVERLESS placed in the `e2e` directory excluding `investigations` and `explore` directories in headless mode using the QA environment and real MKI projects.| +| cypress:run:qa:serverless:explore | Runs all tests tagged as SERVERLESS in the `e2e/explore` directory in headless mode using the QA environment and real MKI prorjects. | +| cypress:run:qa:serverless:investigations | Runs all tests tagged as SERVERLESS in the `e2e/investigations` directory in headless mode using the QA environment and reak MKI projects. | + +Please note that all the headless mode commands do not open the Cypress UI and are typically used in CI/CD environments. The scripts that open the Cypress UI are useful for development and debugging. + + +#### Setup required + +Setup a valid Elastic Cloud API key for QA environment: + +1. Navigate to QA environment. +2. Click on the `User menu button` located on the top right of the header. +3. Click on `Organization`. +4. Click on the `API keys` tab. +5. Click on `Create API key` button. +6. Add a name, set an expiration date, assign an organization owner role. +7. Click on `Create API key` +8. Save the value of the key + +Store the saved key on `~/.elastic/cloud.json` using the following format: + +```json +{ + "api_key": { + "qa": "" + } +} +``` + +#### Known limitations +- Currently RBAC cannot be tested. + +#### PLIs + +When running serverless Cypress tests on QA environment, the following PLIs are set by default: +``` + { product_line: 'security', product_tier: 'complete' }, + { product_line: 'endpoint', product_tier: 'complete' }, + { product_line: 'cloud', product_tier: 'complete' }, +``` + +With the above configuration we'll be able to cover most of the scenarios, but there are some cases were we might want to use a different configuration. In that case, we just need to pass to the header of the test, which is the configuration we want for it. + +```typescript +describe( + 'Entity Analytics Dashboard in Serverless', + { + tags: '@serverless', + env: { + ftrConfig: { + productTypes: [ + { product_line: 'security', product_tier: 'essentials' }, + { product_line: 'endpoint', product_tier: 'essentials' }, + ], + }, + }, + }, +``` + +For test developing or test debugging purposes on QA, you have avaialable the following options: + +``` +yarn cypress:open:qa:serverless --tier +``` + +The above command will open the Cypress UI with all tests in the `e2e` directory tagged as SERVERLESS. This also creates an MKI project in console.qa enviornment with the passed tier essentials or complete. If no flag is passed, the project will be cretaed as complete. + +``` +yarn cypress:open:qa:serverless --no-endpoint-addon +``` + +The above command will open the Cypress UI with all tests in the `e2e` directory tagged as SERVERLESS. This also creates an MKI project in console.qa enviornment without the endpoint add-on. + +``` +yarn cypress:open:qa:serverless --no-cloud-addon +``` + +The above command will open the Cypress UI with all tests in the `e2e` directory tagged as SERVERLESS. This also creates an MKI project in console.qa enviornment without the cloud add-on. + +Note that all the above flags can be combined. + + ## Development Best Practices Below you will a set of best practices that should be followed when writing Cypress tests. diff --git a/x-pack/test/security_solution_cypress/cypress/cypress_ci_serverless_qa.config.ts b/x-pack/test/security_solution_cypress/cypress/cypress_ci_serverless_qa.config.ts index 4688cbe343e1c..342c3da34bef6 100644 --- a/x-pack/test/security_solution_cypress/cypress/cypress_ci_serverless_qa.config.ts +++ b/x-pack/test/security_solution_cypress/cypress/cypress_ci_serverless_qa.config.ts @@ -41,6 +41,7 @@ export default defineCypressConfig({ specPattern: './cypress/e2e/**/*.cy.ts', setupNodeEvents(on, config) { esArchiver(on, config); + process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0'; // eslint-disable-next-line @typescript-eslint/no-var-requires require('@cypress/grep/src/plugin')(config); return config; diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/detection_alerts/alert_status.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/detection_alerts/alert_status.cy.ts index 2ec99abb00db4..e7f17ddcc8cb2 100644 --- a/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/detection_alerts/alert_status.cy.ts +++ b/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/detection_alerts/alert_status.cy.ts @@ -37,7 +37,8 @@ import { visit } from '../../../tasks/navigation'; import { ALERTS_URL } from '../../../urls/navigation'; -describe('Changing alert status', { tags: ['@ess', '@serverless'] }, () => { +// FLAKY: https://github.com/elastic/kibana/issues/169091 +describe.skip('Changing alert status', { tags: ['@ess', '@serverless'] }, () => { before(() => { cy.task('esArchiverLoad', { archiveName: 'auditbeat_multiple' }); }); diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/exceptions/entry/use_value_list.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/exceptions/entry/use_value_list.cy.ts index 530114585fa1c..39c19bdf39f3e 100644 --- a/x-pack/test/security_solution_cypress/cypress/e2e/exceptions/entry/use_value_list.cy.ts +++ b/x-pack/test/security_solution_cypress/cypress/e2e/exceptions/entry/use_value_list.cy.ts @@ -47,7 +47,8 @@ const goToRulesAndOpenValueListModal = () => { openValueListsModal(); }; -describe('Use Value list in exception entry', { tags: ['@ess', '@serverless'] }, () => { +// FLAKY: https://github.com/elastic/kibana/issues/171252 +describe.skip('Use Value list in exception entry', { tags: ['@ess', '@serverless'] }, () => { before(() => { cy.task('esArchiverLoad', { archiveName: 'exceptions' }); }); diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/exceptions/shared_exception_lists_management/manage_exceptions.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/exceptions/shared_exception_lists_management/manage_exceptions.cy.ts index 023140d420f2a..9f64fac5f1512 100644 --- a/x-pack/test/security_solution_cypress/cypress/e2e/exceptions/shared_exception_lists_management/manage_exceptions.cy.ts +++ b/x-pack/test/security_solution_cypress/cypress/e2e/exceptions/shared_exception_lists_management/manage_exceptions.cy.ts @@ -42,7 +42,9 @@ import { import { visitRuleDetailsPage } from '../../../tasks/rule_details'; import { deleteEndpointExceptionList, deleteExceptionLists } from '../../../tasks/common'; -describe('Add, edit and delete exception', { tags: ['@ess', '@serverless'] }, () => { +// https://github.com/elastic/kibana/issues/171235 +// FLAKY: https://github.com/elastic/kibana/issues/171242 +describe.skip('Add, edit and delete exception', { tags: ['@ess', '@serverless'] }, () => { beforeEach(() => { login(); deleteExceptionLists(); diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/explore/overview/overview.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/explore/overview/overview.cy.ts index 1205d2420b7ab..f857805462877 100644 --- a/x-pack/test/security_solution_cypress/cypress/e2e/explore/overview/overview.cy.ts +++ b/x-pack/test/security_solution_cypress/cypress/e2e/explore/overview/overview.cy.ts @@ -16,7 +16,7 @@ import { OVERVIEW_URL } from '../../../urls/navigation'; import { createTimeline, favoriteTimeline } from '../../../tasks/api_calls/timelines'; import { getTimeline } from '../../../objects/timeline'; -describe('Overview Page', { tags: ['@ess', '@serverless', '@serverlessQA'] }, () => { +describe('Overview Page', { tags: ['@ess', '@serverless'] }, () => { before(() => { cy.task('esArchiverLoad', { archiveName: 'overview' }); }); diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/investigations/alerts/alerts_charts.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/investigations/alerts/alerts_charts.cy.ts index 426193bbf72ba..448687ae956c5 100644 --- a/x-pack/test/security_solution_cypress/cypress/e2e/investigations/alerts/alerts_charts.cy.ts +++ b/x-pack/test/security_solution_cypress/cypress/e2e/investigations/alerts/alerts_charts.cy.ts @@ -37,7 +37,7 @@ describe( selectAlertsHistogram(); }); - it('Filter in/out should add a filter to KQL bar', function () { + it('Filter in should add a filter to KQL bar', function () { const expectedNumberOfAlerts = 1; clickAlertsHistogramLegend(); clickAlertsHistogramLegendFilterFor(ruleConfigs.name); @@ -46,7 +46,9 @@ describe( `kibana.alert.rule.name: ${ruleConfigs.name}` ); cy.get(ALERTS_COUNT).should('have.text', `${expectedNumberOfAlerts} alert`); + }); + it('Filter out should add a filter to KQL bar', function () { clickAlertsHistogramLegend(); clickAlertsHistogramLegendFilterOut(ruleConfigs.name); cy.get(GLOBAL_SEARCH_BAR_FILTER_ITEM).should( diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/investigations/timelines/creation.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/investigations/timelines/creation.cy.ts index dc292818a3395..1b69b314daf75 100644 --- a/x-pack/test/security_solution_cypress/cypress/e2e/investigations/timelines/creation.cy.ts +++ b/x-pack/test/security_solution_cypress/cypress/e2e/investigations/timelines/creation.cy.ts @@ -148,12 +148,11 @@ describe('Timelines', (): void => { } ); - // FLAKY: https://github.com/elastic/kibana/issues/170691 - describe.skip('shows the different timeline states', () => { + describe('shows the different timeline states', () => { before(() => { login(); visitWithTimeRange(OVERVIEW_URL); - openTimelineUsingToggle(); + createNewTimeline(); }); it('should show the correct timeline status', { tags: ['@ess', '@serverless'] }, () => { diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/investigations/timelines/pagination.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/investigations/timelines/pagination.cy.ts index f16f7120dd0fb..dcf847224067a 100644 --- a/x-pack/test/security_solution_cypress/cypress/e2e/investigations/timelines/pagination.cy.ts +++ b/x-pack/test/security_solution_cypress/cypress/e2e/investigations/timelines/pagination.cy.ts @@ -24,7 +24,8 @@ import { hostsUrl } from '../../../urls/navigation'; // Flaky on serverless const defaultPageSize = 25; -describe('Pagination', { tags: ['@ess', '@serverless'] }, () => { +// FLAKY: https://github.com/elastic/kibana/issues/169413 +describe.skip('Pagination', { tags: ['@ess', '@serverless'] }, () => { before(() => { cy.task('esArchiverLoad', { archiveName: 'timeline' }); }); diff --git a/x-pack/test/security_solution_cypress/package.json b/x-pack/test/security_solution_cypress/package.json index 0e34d7867d37a..e43f32a447575 100644 --- a/x-pack/test/security_solution_cypress/package.json +++ b/x-pack/test/security_solution_cypress/package.json @@ -28,6 +28,7 @@ "cypress:changed-specs-only:serverless": "yarn cypress:serverless --changed-specs-only --env burn=5", "cypress:burn:serverless": "yarn cypress:serverless --env burn=2", "cypress:qa:serverless": "TZ=UTC NODE_OPTIONS=--openssl-legacy-provider node ../../plugins/security_solution/scripts/start_cypress_parallel_serverless --config-file ../../test/security_solution_cypress/cypress/cypress_ci_serverless_qa.config.ts", + "cypress:open:qa:serverless": "yarn cypress:qa:serverless open", "cypress:run:qa:serverless": "yarn cypress:qa:serverless --spec './cypress/e2e/!(investigations|explore)/**/*.cy.ts'", "cypress:run:qa:serverless:investigations": "yarn cypress:qa:serverless --spec './cypress/e2e/investigations/**/*.cy.ts'", "cypress:run:qa:serverless:explore": "yarn cypress:qa:serverless --spec './cypress/e2e/explore/**/*.cy.ts'" diff --git a/x-pack/test/spaces_api_integration/common/plugins/spaces_test_plugin/server/index.ts b/x-pack/test/spaces_api_integration/common/plugins/spaces_test_plugin/server/index.ts index 1db5fe493b35b..e30ef09b951ee 100644 --- a/x-pack/test/spaces_api_integration/common/plugins/spaces_test_plugin/server/index.ts +++ b/x-pack/test/spaces_api_integration/common/plugins/spaces_test_plugin/server/index.ts @@ -7,6 +7,6 @@ import { Plugin } from './plugin'; -export function plugin() { +export async function plugin() { return new Plugin(); } diff --git a/x-pack/test/tsconfig.json b/x-pack/test/tsconfig.json index 61c42a76f3d9d..025dff494c5fe 100644 --- a/x-pack/test/tsconfig.json +++ b/x-pack/test/tsconfig.json @@ -86,7 +86,6 @@ "@kbn/data-views-plugin", "@kbn/datemath", "@kbn/safer-lodash-set", - "@kbn/securitysolution-rules", "@kbn/es-archiver", "@kbn/config-schema", "@kbn/kubernetes-security-plugin", @@ -146,5 +145,10 @@ "@kbn/coloring", "@kbn/es", "@kbn/metrics-data-access-plugin", + "@kbn/dataset-quality-plugin", + "@kbn/reporting-export-types-csv-common", + "@kbn/reporting-export-types-pdf-common", + "@kbn/reporting-export-types-png-common", + "@kbn/reporting-common", ] } diff --git a/x-pack/test/ui_capabilities/common/plugins/foo_plugin/server/index.ts b/x-pack/test/ui_capabilities/common/plugins/foo_plugin/server/index.ts index 7bb8b446dcc79..4698b8c59c8f4 100644 --- a/x-pack/test/ui_capabilities/common/plugins/foo_plugin/server/index.ts +++ b/x-pack/test/ui_capabilities/common/plugins/foo_plugin/server/index.ts @@ -8,7 +8,7 @@ import { CoreSetup, Plugin } from '@kbn/core/server'; import { PluginSetupContract as FeaturesPluginSetupContract } from '@kbn/features-plugin/server'; -export const plugin = () => new FooPlugin(); +export const plugin = async () => new FooPlugin(); interface SetupDeps { features: FeaturesPluginSetupContract; diff --git a/x-pack/test_serverless/api_integration/test_suites/common/reporting/download_csv_dashboard.ts b/x-pack/test_serverless/api_integration/test_suites/common/reporting/download_csv_dashboard.ts index 6548b76f08bd5..b709e3b43bc25 100644 --- a/x-pack/test_serverless/api_integration/test_suites/common/reporting/download_csv_dashboard.ts +++ b/x-pack/test_serverless/api_integration/test_suites/common/reporting/download_csv_dashboard.ts @@ -8,7 +8,7 @@ import { X_ELASTIC_INTERNAL_ORIGIN_REQUEST } from '@kbn/core-http-common'; import expect from '@kbn/expect'; import { INTERNAL_ROUTES } from '@kbn/reporting-plugin/common/constants'; -import { JobParamsDownloadCSV } from '@kbn/reporting-plugin/server/export_types/csv_searchsource_immediate/types'; +import type { JobParamsDownloadCSV } from '@kbn/reporting-export-types-csv-common'; import { FtrProviderContext } from '../../../ftr_provider_context'; const ELASTIC_USERNAME = 'elastic_serverless'; diff --git a/x-pack/test_serverless/functional/services/index.ts b/x-pack/test_serverless/functional/services/index.ts index dd4ec37f21501..a1c381331f6bc 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 { SvlReportingServiceProvider } from './svl_reporting'; +import { LogsSynthtraceProvider } from './log'; export const services = { // deployment agnostic FTR services @@ -31,4 +32,7 @@ export const services = { svlCases: SvlCasesServiceProvider, svlMl: MachineLearningProvider, svlReportingApi: SvlReportingServiceProvider, + + // log services + svlLogsSynthtraceClient: LogsSynthtraceProvider, }; diff --git a/x-pack/test_serverless/functional/services/log/index.ts b/x-pack/test_serverless/functional/services/log/index.ts new file mode 100644 index 0000000000000..0aadf7b9bf292 --- /dev/null +++ b/x-pack/test_serverless/functional/services/log/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 { createLogger, LogLevel, LogsSynthtraceEsClient } from '@kbn/apm-synthtrace'; +import { FtrProviderContext } from '../../ftr_provider_context'; + +export function LogsSynthtraceProvider(context: FtrProviderContext) { + return new LogsSynthtraceEsClient({ + client: context.getService('es'), + logger: createLogger(LogLevel.info), + refreshAfterIndex: true, + }); +} diff --git a/x-pack/test_serverless/functional/test_suites/common/examples/data_view_field_editor_example/index.ts b/x-pack/test_serverless/functional/test_suites/common/examples/data_view_field_editor_example/index.ts index 106f504cae82b..f8f96c0bbdd20 100644 --- a/x-pack/test_serverless/functional/test_suites/common/examples/data_view_field_editor_example/index.ts +++ b/x-pack/test_serverless/functional/test_suites/common/examples/data_view_field_editor_example/index.ts @@ -55,7 +55,15 @@ export default function ({ getService, getPageObjects, loadTestFile }: FtrProvid } return false; }); - await PageObjects.settings.createIndexPattern('blogs', null); + // re-create default dataview : default_all_data_id which was created when serverles_search plugin was started. + await PageObjects.settings.createIndexPattern( + 'blogs', + null, + true, + 'default_all_data_id', + 'default:all-data' + ); + await PageObjects.common.navigateToApp('dataViewFieldEditorExample'); }); diff --git a/x-pack/test_serverless/functional/test_suites/common/reporting/management.ts b/x-pack/test_serverless/functional/test_suites/common/reporting/management.ts index c36000889d481..90be1b602441a 100644 --- a/x-pack/test_serverless/functional/test_suites/common/reporting/management.ts +++ b/x-pack/test_serverless/functional/test_suites/common/reporting/management.ts @@ -6,8 +6,10 @@ */ import { DISCOVER_APP_LOCATOR } from '@kbn/discover-plugin/common'; -import { CSV_REPORT_TYPE_V2 } from '@kbn/reporting-plugin/common/constants'; -import type { JobParamsCsvFromSavedObject } from '@kbn/reporting-plugin/common/types'; +import { + CSV_REPORT_TYPE_V2, + JobParamsCsvFromSavedObject, +} from '@kbn/reporting-export-types-csv-common'; import { FtrProviderContext } from '../../../ftr_provider_context'; export default ({ getPageObjects, getService }: FtrProviderContext) => { diff --git a/x-pack/test_serverless/functional/test_suites/observability/observability_log_explorer/app.ts b/x-pack/test_serverless/functional/test_suites/observability/observability_log_explorer/app.ts index fc03be6e0c125..271bba6b45035 100644 --- a/x-pack/test_serverless/functional/test_suites/observability/observability_log_explorer/app.ts +++ b/x-pack/test_serverless/functional/test_suites/observability/observability_log_explorer/app.ts @@ -5,15 +5,19 @@ * 2.0. */ import expect from '@kbn/expect'; +import { log, timerange } from '@kbn/apm-synthtrace-client'; import { FtrProviderContext } from '../../../ftr_provider_context'; -export default function ({ getPageObjects }: FtrProviderContext) { +export default function ({ getPageObjects, getService }: FtrProviderContext) { const PageObjects = getPageObjects([ 'observabilityLogExplorer', 'svlCommonNavigation', 'svlCommonPage', ]); + const synthtrace = getService('svlLogsSynthtraceClient'); + const dataGrid = getService('dataGrid'); + describe('Application', () => { before(async () => { await PageObjects.svlCommonPage.login(); @@ -25,6 +29,7 @@ export default function ({ getPageObjects }: FtrProviderContext) { it('is shown in the global search', async () => { await PageObjects.observabilityLogExplorer.navigateTo(); + await PageObjects.svlCommonNavigation.search.showSearch(); await PageObjects.svlCommonNavigation.search.searchFor('log explorer'); @@ -33,5 +38,32 @@ export default function ({ getPageObjects }: FtrProviderContext) { await PageObjects.svlCommonNavigation.search.hideSearch(); }); + + it('should load logs', async () => { + const from = '2023-08-03T10:24:14.035Z'; + const to = '2023-08-03T10:24:14.091Z'; + const COUNT = 5; + await synthtrace.index(generateLogsData({ from, to, count: COUNT })); + await PageObjects.observabilityLogExplorer.navigateTo(); + const docCount = await dataGrid.getDocCount(); + + expect(docCount).to.be(COUNT); + await synthtrace.clean(); + }); }); } + +function generateLogsData({ from, to, count = 1 }: { from: string; to: string; count: number }) { + const range = timerange(from, to); + + return range + .interval('1m') + .rate(1) + .generator((timestamp) => + Array(count) + .fill(0) + .map(() => { + return log.create().message('A sample log').timestamp(timestamp); + }) + ); +} diff --git a/x-pack/test_serverless/functional/test_suites/search/cases/attachment_framework.ts b/x-pack/test_serverless/functional/test_suites/search/cases/attachment_framework.ts index bff6144d44bb2..3cf087eb1ae9b 100644 --- a/x-pack/test_serverless/functional/test_suites/search/cases/attachment_framework.ts +++ b/x-pack/test_serverless/functional/test_suites/search/cases/attachment_framework.ts @@ -39,7 +39,7 @@ export default ({ getPageObject, getService }: FtrProviderContext) => { await dashboard.clickNewDashboard(); - await lens.createAndAddLensFromDashboard({}); + await lens.createAndAddLensFromDashboard({ ignoreTimeFilter: true }); }); after(async () => { diff --git a/x-pack/test_serverless/functional/test_suites/search/dashboards/build_dashboard.ts b/x-pack/test_serverless/functional/test_suites/search/dashboards/build_dashboard.ts index d91d296c75624..0ae48d641be4b 100644 --- a/x-pack/test_serverless/functional/test_suites/search/dashboards/build_dashboard.ts +++ b/x-pack/test_serverless/functional/test_suites/search/dashboards/build_dashboard.ts @@ -48,7 +48,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { }); it('can add a lens panel by value', async () => { - await PageObjects.lens.createAndAddLensFromDashboard({}); + await PageObjects.lens.createAndAddLensFromDashboard({ ignoreTimeFilter: true }); const newPanelCount = await PageObjects.dashboard.getPanelCount(); expect(newPanelCount).to.eql(1); }); diff --git a/x-pack/test_serverless/functional/test_suites/search/empty_page.ts b/x-pack/test_serverless/functional/test_suites/search/default_dataview.ts similarity index 66% rename from x-pack/test_serverless/functional/test_suites/search/empty_page.ts rename to x-pack/test_serverless/functional/test_suites/search/default_dataview.ts index 18af7995b1419..2beb234f688f4 100644 --- a/x-pack/test_serverless/functional/test_suites/search/empty_page.ts +++ b/x-pack/test_serverless/functional/test_suites/search/default_dataview.ts @@ -13,7 +13,7 @@ export default function ({ getPageObject, getService }: FtrProviderContext) { const svlCommonNavigation = getPageObject('svlCommonNavigation'); const svlCommonPage = getPageObject('svlCommonPage'); - describe('empty pages', function () { + describe('default dataView', function () { // Error: expected testSubject(kbnOverviewElasticsearchGettingStarted) to exist this.tags(['failsOnMKI']); before(async () => { @@ -25,28 +25,32 @@ export default function ({ getPageObject, getService }: FtrProviderContext) { await svlCommonPage.forceLogout(); }); - it('should show search specific empty page in discover', async () => { + it('should show dashboard but with no data', async () => { await svlCommonNavigation.sidenav.clickLink({ deepLinkId: 'discover' }); await testSubjects.existOrFail('~breadcrumb-deepLinkId-discover'); - await testSubjects.existOrFail('kbnOverviewElasticsearchGettingStarted'); - await testSubjects.click('kbnOverviewElasticsearchGettingStarted'); - await svlCommonNavigation.breadcrumbs.expectBreadcrumbExists({ text: 'Get started' }); + await testSubjects.existOrFail('discover-dataView-switch-link'); + await testSubjects.click('discover-dataView-switch-link'); + await testSubjects.existOrFail('indexPattern-add-field'); + await svlCommonNavigation.breadcrumbs.expectBreadcrumbExists({ text: 'Discover' }); }); - it('should show search specific empty page in visualize', async () => { - await svlCommonNavigation.sidenav.clickLink({ deepLinkId: 'visualize' }); - await testSubjects.existOrFail('~breadcrumb-deepLinkId-visualize'); - await testSubjects.existOrFail('kbnOverviewElasticsearchGettingStarted'); - await testSubjects.click('kbnOverviewElasticsearchGettingStarted'); - await svlCommonNavigation.breadcrumbs.expectBreadcrumbExists({ text: 'Get started' }); - }); - - it('should show search specific empty page in dashboards', async () => { + it('should show dashboard but with no data in dashboard', async () => { await svlCommonNavigation.sidenav.clickLink({ deepLinkId: 'dashboards' }); await testSubjects.existOrFail('~breadcrumb-deepLinkId-dashboards'); - await testSubjects.existOrFail('kbnOverviewElasticsearchGettingStarted'); - await testSubjects.click('kbnOverviewElasticsearchGettingStarted'); - await svlCommonNavigation.breadcrumbs.expectBreadcrumbExists({ text: 'Get started' }); + await testSubjects.existOrFail('emptyListPrompt'); + await testSubjects.click('newItemButton'); + await svlCommonNavigation.breadcrumbs.expectBreadcrumbExists({ + text: 'Editing New Dashboard', + }); + }); + + it('should show dashboard but with no data in visualize', async () => { + await svlCommonNavigation.sidenav.clickLink({ deepLinkId: 'visualize' }); + await testSubjects.existOrFail('~breadcrumb-deepLinkId-visualize'); + await testSubjects.existOrFail('top-nav'); + await testSubjects.click('newItemButton'); + await testSubjects.existOrFail('visType-lens'); + await svlCommonNavigation.breadcrumbs.expectBreadcrumbExists({ text: 'Visualizations' }); }); }); } 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 6ed8a9f62c222..6d0987d0292ce 100644 --- a/x-pack/test_serverless/functional/test_suites/search/index.ts +++ b/x-pack/test_serverless/functional/test_suites/search/index.ts @@ -10,7 +10,7 @@ import { FtrProviderContext } from '../../ftr_provider_context'; export default function ({ loadTestFile }: FtrProviderContext) { describe('serverless search UI', function () { loadTestFile(require.resolve('./landing_page')); - loadTestFile(require.resolve('./empty_page')); + loadTestFile(require.resolve('./default_dataview')); loadTestFile(require.resolve('./navigation')); loadTestFile(require.resolve('./cases/attachment_framework')); loadTestFile(require.resolve('./dashboards/build_dashboard')); diff --git a/x-pack/test_serverless/tsconfig.json b/x-pack/test_serverless/tsconfig.json index e587356636d61..b4fdeb93c91cf 100644 --- a/x-pack/test_serverless/tsconfig.json +++ b/x-pack/test_serverless/tsconfig.json @@ -63,5 +63,8 @@ "@kbn/cloud-security-posture-plugin", "@kbn/reporting-plugin", "@kbn/management-settings-ids", + "@kbn/apm-synthtrace", + "@kbn/apm-synthtrace-client", + "@kbn/reporting-export-types-csv-common", ] } diff --git a/yarn.lock b/yarn.lock index 01e9ef5b1bc90..2551fb95cdf74 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4593,10 +4593,6 @@ version "0.0.0" uid "" -"@kbn/generate-csv-types@link:packages/kbn-generate-csv-types": - version "0.0.0" - uid "" - "@kbn/generate-csv@link:packages/kbn-generate-csv": version "0.0.0" uid "" @@ -5293,10 +5289,46 @@ version "0.0.0" uid "" +"@kbn/reporting-export-types-csv-common@link:packages/kbn-reporting/export_types/csv_common": + version "0.0.0" + uid "" + +"@kbn/reporting-export-types-csv@link:packages/kbn-reporting/export_types/csv": + version "0.0.0" + uid "" + +"@kbn/reporting-export-types-pdf-common@link:packages/kbn-reporting/export_types/pdf_common": + version "0.0.0" + uid "" + +"@kbn/reporting-export-types-pdf@link:packages/kbn-reporting/export_types/pdf": + version "0.0.0" + uid "" + +"@kbn/reporting-export-types-png-common@link:packages/kbn-reporting/export_types/png_common": + version "0.0.0" + uid "" + +"@kbn/reporting-export-types-png@link:packages/kbn-reporting/export_types/png": + version "0.0.0" + uid "" + +"@kbn/reporting-mocks-server@link:packages/kbn-reporting/mocks_server": + version "0.0.0" + uid "" + "@kbn/reporting-plugin@link:x-pack/plugins/reporting": version "0.0.0" uid "" +"@kbn/reporting-public@link:packages/kbn-reporting/public": + version "0.0.0" + uid "" + +"@kbn/reporting-server@link:packages/kbn-reporting/server": + version "0.0.0" + uid "" + "@kbn/resizable-layout-examples-plugin@link:examples/resizable_layout_examples": version "0.0.0" uid "" @@ -11506,11 +11538,16 @@ axe-core@^3.5.5: resolved "https://registry.yarnpkg.com/axe-core/-/axe-core-3.5.6.tgz#e762a90d7f6dbd244ceacb4e72760ff8aad521b5" integrity sha512-LEUDjgmdJoA3LqklSTwKYqkjcZ4HKc4ddIYGSAiSkr46NTjzg2L9RNB+lekO9P7Dlpa87+hBtzc2Fzn/+GUWMQ== -axe-core@^4.2.0, axe-core@^4.6.1, axe-core@^4.6.2: +axe-core@^4.2.0, axe-core@^4.6.2: version "4.7.2" resolved "https://registry.yarnpkg.com/axe-core/-/axe-core-4.7.2.tgz#040a7342b20765cb18bb50b628394c21bccc17a0" integrity sha512-zIURGIS1E1Q4pcrMjp+nnEh+16G56eG/MUllJH8yEvw7asDo7Ac9uhC9KIH5jzpITueEZolfYglnCGIuSBz39g== +axe-core@^4.8.2: + version "4.8.2" + resolved "https://registry.yarnpkg.com/axe-core/-/axe-core-4.8.2.tgz#2f6f3cde40935825cf4465e3c1c9e77b240ff6ae" + integrity sha512-/dlp0fxyM3R8YW7MFzaHWXrf4zzbr0vaYb23VBFCl83R7nWNPg/yaQw2Dc8jzCMmDVLhSdzH8MjrsuIUuvX+6g== + axios@^0.21.1: version "0.21.4" resolved "https://registry.yarnpkg.com/axios/-/axios-0.21.4.tgz#c67b90dc0568e5c1cf2b0b858c43ba28e2eda575"